erblint-github 0.2.0 → 0.3.0

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: ae2332b3396f7d9533f5a13c71cce75e048308f5d1ebf7a351dca556408652d2
4
- data.tar.gz: a491e50f3c4c1da08e570514bba69f11f5631c1d82a241e236269ebed1a86f0b
3
+ metadata.gz: 6b2a29a79e8d05ae92a33bff53b8a210d3ae35658e4e331fb3f7b7c9ca259147
4
+ data.tar.gz: 6e551b63af42992248a0b1965e50d9954c44e3596bc5feed0ba6a2eb7399d1bf
5
5
  SHA512:
6
- metadata.gz: d2e983445be5d46bdb88ffc2a8cf3be88aa09dfe1745eca84736ec98830e13b5da606c5b0022b9595b4f5c8435313267d948651d11ea6d64f465700600fcc794
7
- data.tar.gz: 31671c8e895599bf10659d9978676c532b87fed47f7deec5e977866e457a347d8c5041d029e49448a2f86348967f5aa0ce8c5ada910015bc583dd1b8b60a6d4e
6
+ metadata.gz: 62bd97d7ece9d2d9082d1424e086b542f25a5b736ee7664636811376cd87b08c2420cbb1c3fef0ab0b769511c6e520d8769c51380647a373efa95b241d8db393
7
+ data.tar.gz: a8c9be52a3b99be842df8b5d34388f3ee8ff2629e369deaaefdea206520440a1e3a5fc18e1a74b5fa2fd774ffd2a6586476ad8dbfb965a3ea9b8dd5dd053b099
data/README.md CHANGED
@@ -23,6 +23,8 @@ require "erblint-github/linters"
23
23
  ```yaml
24
24
  ---
25
25
  linters:
26
+ GitHub::Accessibility::AriaLabelIsWellFormatted:
27
+ enabled: true
26
28
  GitHub::Accessibility::AvoidBothDisabledAndAriaDisabled:
27
29
  enabled: true
28
30
  GitHub::Accessibility::AvoidGenericLinkText:
@@ -33,7 +35,7 @@ linters:
33
35
  enabled: true
34
36
  GitHub::Accessibility::ImageHasAlt:
35
37
  enabled: true
36
- GitHub::Accessibility::LandmarkHasLabel:
38
+ GitHub::Accessibility::NavigationHasLabel:
37
39
  enabled: true
38
40
  GitHub::Accessibility::LinkHasHref:
39
41
  enabled: true
@@ -55,10 +57,11 @@ linters:
55
57
 
56
58
  ## Rules
57
59
 
60
+ - [GitHub::Accessibility::AriaLabelIsWellFormatted](./docs/rules/accessibility/aria-label-is-well-formatted.md)
58
61
  - [GitHub::Accessibility::AvoidBothDisabledAndAriaDisabled](./docs/rules/accessibility/avoid-both-disabled-and-aria-disabled.md)
59
62
  - [GitHub::Accessibility::AvoidGenericLinkText](./docs/rules/accessibility/avoid-generic-link-text.md)
60
63
  - [GitHub::Accessibility::DisabledAttribute](./docs/rules/accessibility/disabled-attribute.md)
61
- - [GitHub::Accessibility::LandmarkHasLabel](./docs/rules/accessibility/landmark-has-label.md)
64
+ - [GitHub::Accessibility::NavigationHasLabel](./docs/rules/accessibility/navigation-has-label.md)
62
65
  - [GitHub::Accessibility::LinkHasHref](./docs/rules/accessibility/link-has-href.md)
63
66
  - [GitHub::Accessibility::NestedInteractiveElements](./docs/rules/accessibility/nested-interactive-elements.md)
64
67
  - [GitHub::Accessibility::IframeHasTitle](./docs/rules/accessibility/iframe-has-title.md)
@@ -8,24 +8,6 @@ module ERBLint
8
8
  module CustomHelpers
9
9
  INTERACTIVE_ELEMENTS = %w[button summary input select textarea a].freeze
10
10
 
11
- def rule_disabled?(processed_source)
12
- processed_source.parser.ast.descendants(:erb).each do |node|
13
- indicator_node, _, code_node, = *node
14
- indicator = indicator_node&.loc&.source
15
- comment = code_node&.loc&.source&.strip
16
- rule_name = simple_class_name
17
-
18
- if indicator == "#" && comment.start_with?("erblint:disable") && comment.match(rule_name)
19
- if @offenses.any?
20
- clear_offenses
21
- else
22
- add_offense(processed_source.to_source_range(code_node.loc),
23
- "Unused erblint:disable comment for #{rule_name}")
24
- end
25
- end
26
- end
27
- end
28
-
29
11
  def counter_correct?(processed_source)
30
12
  comment_node = nil
31
13
  expected_count = 0
@@ -52,10 +34,10 @@ module ERBLint
52
34
  first_offense = @offenses[0]
53
35
 
54
36
  if comment_node.nil?
55
- add_offense(processed_source.to_source_range(first_offense.source_range), "#{rule_name}: If you must, add <%# erblint:counter #{rule_name} #{offenses_count} %> to bypass this check.", "<%# erblint:counter #{rule_name} #{offenses_count} %>")
37
+ add_offense(processed_source.to_source_range(first_offense.source_range), "#{rule_name}: If you must, add <%# erblint:disable #{rule_name} %> at the end of the offending line to bypass this check. See https://github.com/shopify/erb-lint#disable-rule-at-offense-level", "<%# erblint:disable #{rule_name} %>")
56
38
  else
57
39
  clear_offenses
58
- add_offense(processed_source.to_source_range(comment_node.loc), "Incorrect erblint:counter number for #{rule_name}. Expected: #{expected_count}, actual: #{offenses_count}.", "<%# erblint:counter #{rule_name} #{offenses_count} %>") if expected_count != offenses_count
40
+ add_offense(processed_source.to_source_range(comment_node.loc), "Incorrect erblint:counter number for #{rule_name}. Expected: #{expected_count}, actual: #{offenses_count}.", "<%# erblint:counter #{rule_name}Counter #{offenses_count} %>") if expected_count != offenses_count
59
41
  end
60
42
  end
61
43
 
@@ -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
@@ -0,0 +1,33 @@
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 NavigationHasLabel < Linter
10
+ include ERBLint::Linters::CustomHelpers
11
+ include LinterRegistry
12
+
13
+ MESSAGE = "The navigation landmark should have a unique accessible name via `aria-label` or `aria-labelledby`. Remember that the name does not need to include `navigation` or `nav` since it will already be announced."
14
+
15
+ def run(processed_source)
16
+ tags(processed_source).each do |tag|
17
+ next if tag.closing?
18
+ next unless possible_attribute_values(tag, "role").include?("navigation") || tag.name == "nav"
19
+ if possible_attribute_values(tag, "aria-label").empty? && possible_attribute_values(tag, "aria-labelledby").empty?
20
+ message = MESSAGE
21
+ if tag.name != "nav"
22
+ message += "Additionally, you can safely drop the `role='navigation'` and replace it with the native HTML `nav` element."
23
+ end
24
+ generate_offense(self.class, processed_source, tag, message)
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ 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.2.0
4
+ version: 0.3.0
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: 2023-04-03 00:00:00.000000000 Z
11
+ date: 2023-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erb_lint
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 5.17.0
33
+ version: 5.18.0
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.17.0
40
+ version: 5.18.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mocha
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 1.44.1
75
+ version: 1.49.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.44.1
82
+ version: 1.49.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop-github
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -105,13 +105,14 @@ files:
105
105
  - README.md
106
106
  - lib/erblint-github/linters.rb
107
107
  - lib/erblint-github/linters/custom_helpers.rb
108
+ - lib/erblint-github/linters/github/accessibility/aria_label_is_well_formatted.rb
108
109
  - lib/erblint-github/linters/github/accessibility/avoid_both_disabled_and_aria_disabled.rb
109
110
  - lib/erblint-github/linters/github/accessibility/avoid_generic_link_text.rb
110
111
  - lib/erblint-github/linters/github/accessibility/disabled_attribute.rb
111
112
  - lib/erblint-github/linters/github/accessibility/iframe_has_title.rb
112
113
  - lib/erblint-github/linters/github/accessibility/image_has_alt.rb
113
- - lib/erblint-github/linters/github/accessibility/landmark_has_label.rb
114
114
  - lib/erblint-github/linters/github/accessibility/link_has_href.rb
115
+ - lib/erblint-github/linters/github/accessibility/navigation_has_label.rb
115
116
  - lib/erblint-github/linters/github/accessibility/nested_interactive_elements.rb
116
117
  - lib/erblint-github/linters/github/accessibility/no_aria_hidden_on_focusable.rb
117
118
  - lib/erblint-github/linters/github/accessibility/no_aria_label_misuse.rb
@@ -1,68 +0,0 @@
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 LandmarkHasLabel < Linter
10
- include ERBLint::Linters::CustomHelpers
11
- include LinterRegistry
12
-
13
- LANDMARK_ROLES = %w[complementary navigation region search].freeze
14
- LANDMARK_TAGS = %w[aside nav section].freeze
15
- MESSAGE = "Landmark elements should have an aria-label attribute, or aria-labelledby if a heading elements exists in the landmark."
16
- ROLE_TAG_MAPPING = { "complementary" => "aside", "navigation" => "nav", "region" => "section" }.freeze
17
-
18
- def get_additional_message(tag, roles)
19
- role_matched = (roles & ROLE_TAG_MAPPING.keys).first
20
- if role_matched
21
- tag_matched = ROLE_TAG_MAPPING[role_matched]
22
-
23
- if tag.name == tag_matched
24
- "The <#{tag_matched}> element will automatically communicate a role of '#{role_matched}'. You can safely drop the role attribute."
25
- else
26
- replace_message = if tag.name == "div"
27
- "If possible replace this tag with a <#{tag_matched}>."
28
- else
29
- "Wrapping this element in a <#{tag_matched}> and setting a label on it is reccomended."
30
- end
31
-
32
- "The <#{tag_matched}> element will automatically communicate a role of '#{role_matched}'. #{replace_message}"
33
- end
34
- elsif roles.include?("search") && tag.name != "form"
35
- "The 'search' role works best when applied to a <form> element. If possible replace this tag with a <form>."
36
- end
37
- end
38
-
39
- class ConfigSchema < LinterConfig
40
- property :counter_enabled, accepts: [true, false], default: false, reader: :counter_enabled?
41
- end
42
- self.config_schema = ConfigSchema
43
-
44
- def run(processed_source)
45
- tags(processed_source).each do |tag|
46
- next if tag.closing?
47
-
48
- possible_roles = possible_attribute_values(tag, "role")
49
- next unless LANDMARK_TAGS.include?(tag.name) && (possible_roles & LANDMARK_ROLES).empty?
50
- next if tag.attributes["aria-label"]&.value&.present? || tag.attributes["aria-labelledby"]&.value&.present?
51
-
52
- message = get_additional_message(tag, possible_roles)
53
- if message
54
- generate_offense(self.class, processed_source, tag, "#{MESSAGE}\n#{message}")
55
- else
56
- generate_offense(self.class, processed_source, tag)
57
- end
58
- end
59
-
60
- if @config.counter_enabled?
61
- counter_correct?(processed_source)
62
- end
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end