erblint-github 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48eba970607504df53f6b0f2ce5cff3b07051148eb1f4dca2fd78fa8287671a9
4
- data.tar.gz: 820da77f5a3ad624c32f4de22817e1c3d80ed755ddbe717368ef97e17e87e262
3
+ metadata.gz: 310138254b0989437e8cf803d52cba66ad005d7cae43b8b6233e638a20e40868
4
+ data.tar.gz: 654d731eb0c99317883327dd401726582d7df70995350d0006b365fe1b9670b6
5
5
  SHA512:
6
- metadata.gz: 34b69cd67df4ea14698098a1331bd787cc9c653cb616f8020c0767478427a41144d177706397eaedc7f7f3767b60758231a000ab45d3fef2dcd8ee07249b49ad
7
- data.tar.gz: d34ed13a0a85b146f4b2eff4e6fcbe00bbe7aef41d7168c6dadb2cc78a3fd49b42cc5dc92e6669cffb7b9bb81cf982495862fb46acb166a49dd63c9813d31d60
6
+ metadata.gz: ce1a90a1c2482b29b406787a1c530614718242de1b9fac828617c2f476db00578872bcddf52037bf8195c71beb8750916e853b5127f4de036aea5771a8edbe2b
7
+ data.tar.gz: 2a1e8844fdae5d352a6798937629e4ae70bea7d3a16c00e1a6de363dcc805044164b55e5166d9ffaf6f288bbdb135c373c2f1b1b40d27ecb0705c2cb616a833c
data/README.md CHANGED
@@ -42,6 +42,7 @@ linters:
42
42
  ## Rules
43
43
 
44
44
  - [GitHub::Accessibility::AvoidBothDisabledAndAriaDisabled](./docs/rules/accessibility/avoid-both-disabled-and-aria-disabled.md)
45
+ - [GitHub::Accessibility::AvoidGenericLinkTextCounter](./docs/rules/accessibility/avoid-generic-link-text-counter.md)
45
46
  - [GitHub::Accessibility::IframeHasTitle](./docs/rules/accessibility/iframe-has-title.md)
46
47
  - [GitHub::Accessibility::ImageHasAlt](./docs/rules/accessibility/image-has-alt.md)
47
48
  - [GitHub::Accessibility::NoAriaLabelMisuseCounter](./docs/rules/accessibility/no-aria-label-misuse-counter.md)
@@ -64,6 +64,13 @@ module ERBLint
64
64
  add_offense(processed_source.to_source_range(tag.loc), offense, replacement)
65
65
  end
66
66
 
67
+ def generate_offense_from_source_range(klass, source_range, message = nil, replacement = nil)
68
+ message ||= klass::MESSAGE
69
+ message += "\nLearn more at https://github.com/github/erblint-github#rules.\n"
70
+ offense = ["#{simple_class_name}:#{message}", source_range.source].join("\n")
71
+ add_offense(source_range, offense, replacement)
72
+ end
73
+
67
74
  def possible_attribute_values(tag, attr_name)
68
75
  value = tag.attributes[attr_name]&.value || nil
69
76
  basic_conditional_code_check(value || "") || [value].compact
@@ -0,0 +1,104 @@
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 AvoidGenericLinkTextCounter < Linter
10
+ include ERBLint::Linters::CustomHelpers
11
+ include LinterRegistry
12
+
13
+ BANNED_GENERIC_TEXT = [
14
+ "Read more",
15
+ "Learn more",
16
+ "Click here",
17
+ "More",
18
+ "Link",
19
+ "Here"
20
+ ].freeze
21
+ MESSAGE = "Avoid using generic link text such as #{BANNED_GENERIC_TEXT.join(', ')} which do not make sense in isolation."
22
+
23
+ def run(processed_source)
24
+ processed_source.ast.children.each_with_index do |node, index|
25
+ next unless node.methods.include?(:type) && node.type == :text
26
+
27
+ text = node.children.join.strip
28
+ # Checks HTML tags
29
+ if banned_text?(text)
30
+ prev_node = processed_source.ast.children[index - 1]
31
+ next_node = processed_source.ast.children[index + 1]
32
+
33
+ next unless tag_type?(prev_node) && tag_type?(next_node)
34
+
35
+ text_node_tag = BetterHtml::Tree::Tag.from_node(node)
36
+ prev_node_tag = BetterHtml::Tree::Tag.from_node(prev_node)
37
+ next_node_tag = BetterHtml::Tree::Tag.from_node(next_node)
38
+
39
+ # We only report if the text is nested between two link tags.
40
+ if link_tag?(prev_node_tag) && link_tag?(next_node_tag) && next_node_tag.closing?
41
+ range = prev_node_tag.loc.begin_pos...text_node_tag.loc.end_pos
42
+ source_range = processed_source.to_source_range(range)
43
+ generate_offense_from_source_range(self.class, source_range)
44
+ end
45
+ end
46
+
47
+ # 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)
59
+ tag = BetterHtml::Tree::Tag.from_node(code_node)
60
+ generate_offense(self.class, processed_source, tag)
61
+ end
62
+ end
63
+ end
64
+ counter_correct?(processed_source)
65
+ end
66
+
67
+ def autocorrect(processed_source, offense)
68
+ return unless offense.context
69
+
70
+ lambda do |corrector|
71
+ if processed_source.file_content.include?("erblint:counter #{simple_class_name}")
72
+ # update the counter if exists
73
+ corrector.replace(offense.source_range, offense.context)
74
+ else
75
+ # add comment with counter if none
76
+ corrector.insert_before(processed_source.source_buffer.source_range, "#{offense.context}\n")
77
+ end
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def banned_text?(text)
84
+ BANNED_GENERIC_TEXT.map(&:downcase).include?(text.downcase)
85
+ end
86
+
87
+ def extract_ruby_node(source)
88
+ BetterHtml::TestHelper::RubyNode.parse(source)
89
+ rescue ::Parser::SyntaxError
90
+ nil
91
+ end
92
+
93
+ def link_tag?(tag_node)
94
+ tag_node.name == "a"
95
+ end
96
+
97
+ def tag_type?(node)
98
+ node.methods.include?(:type) && node.type == :tag
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -10,8 +10,8 @@ module ERBLint
10
10
  include ERBLint::Linters::CustomHelpers
11
11
  include LinterRegistry
12
12
 
13
- MESSAGE = "<iframe> with meaningful content should have a title attribute that identifies the content."\
14
- " If <iframe> has no meaningful content, hide it from assistive technology with `aria-hidden='true'`."\
13
+ MESSAGE = "`<iframe>` with meaningful content should have a title attribute that identifies the content."\
14
+ " If `<iframe>` has no meaningful content, hide it from assistive technology with `aria-hidden='true'`."\
15
15
 
16
16
  def run(processed_source)
17
17
  tags(processed_source).each do |tag|
data/lib/tasks/docs.rake CHANGED
@@ -4,10 +4,9 @@ namespace :docs do
4
4
  task :coverage do
5
5
  require "erb_lint/all"
6
6
  require "erblint-github/linters"
7
-
8
- Dir[File.join(__dir__, "linters", "github/**/*.rb")].sort.each do |file|
7
+ Dir[File.join("lib", "erblint-github", "linters", "github/**/*.rb")].sort.each do |file|
9
8
  rule_documentation_path = file
10
- .gsub("#{__dir__}linters/github/", "docs/rules/")
9
+ .gsub("lib/erblint-github/linters/github/", "docs/rules/")
11
10
  .gsub(".rb", ".md")
12
11
  .tr("_", "-")
13
12
  raise "Missing rule documentation. Please document rule in #{rule_documentation_path}" unless File.file?(rule_documentation_path.to_s)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :tests do
4
+ task :coverage do
5
+ require "erb_lint/all"
6
+ require "erblint-github/linters"
7
+
8
+ Dir[File.join("lib", "erblint-github", "linters", "github/**/*.rb")].sort.each do |file|
9
+ test_path = file.gsub("lib/erblint-github/linters/github/", "test/linters/").gsub(".rb", "_test.rb")
10
+ raise "Missing test. Please add test in #{test_path}" unless File.file?(test_path.to_s)
11
+ end
12
+ puts "All rules have test coverage."
13
+ end
14
+ end
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.5
4
+ version: 0.0.6
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-02-23 00:00:00.000000000 Z
11
+ date: 2022-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erb_lint
@@ -16,84 +16,84 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.1'
19
+ version: 0.1.1
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.1'
26
+ version: 0.1.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5.14'
33
+ version: '5.15'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '5.14'
40
+ version: '5.15'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mocha
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1'
47
+ version: '1.14'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1'
54
+ version: '1.14'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '12.0'
61
+ version: 13.0.6
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '12.0'
68
+ version: 13.0.6
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 1.13.0
75
+ version: 1.30.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 1.13.0
82
+ version: 1.30.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop-github
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.16.0
89
+ version: 0.17.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.16.0
96
+ version: 0.17.0
97
97
  description: Template style checking for GitHub Ruby repositories
98
98
  email:
99
99
  - opensource+erblint-github@github.com
@@ -106,6 +106,7 @@ files:
106
106
  - lib/erblint-github/linters.rb
107
107
  - lib/erblint-github/linters/custom_helpers.rb
108
108
  - lib/erblint-github/linters/github/accessibility/avoid_both_disabled_and_aria_disabled.rb
109
+ - lib/erblint-github/linters/github/accessibility/avoid_generic_link_text_counter.rb
109
110
  - lib/erblint-github/linters/github/accessibility/iframe_has_title.rb
110
111
  - lib/erblint-github/linters/github/accessibility/image_has_alt.rb
111
112
  - lib/erblint-github/linters/github/accessibility/no_aria_label_misuse_counter.rb
@@ -113,10 +114,12 @@ files:
113
114
  - lib/erblint-github/linters/github/accessibility/no_redundant_image_alt.rb
114
115
  - lib/erblint-github/linters/github/accessibility/no_title_attribute_counter.rb
115
116
  - lib/tasks/docs.rake
117
+ - lib/tasks/tests.rake
116
118
  homepage: https://github.com/github/erblint-github
117
119
  licenses:
118
120
  - MIT
119
- metadata: {}
121
+ metadata:
122
+ rubygems_mfa_required: 'true'
120
123
  post_install_message:
121
124
  rdoc_options: []
122
125
  require_paths:
@@ -125,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
128
  requirements:
126
129
  - - ">="
127
130
  - !ruby/object:Gem::Version
128
- version: 2.5.0
131
+ version: 2.6.0
129
132
  required_rubygems_version: !ruby/object:Gem::Requirement
130
133
  requirements:
131
134
  - - ">="