erblint-github 0.2.1 → 0.3.1

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: 241e053b11c2e8e99f2393e5810b8bf9206e9db587a579c7ba20f67575f07874
4
- data.tar.gz: 60470f738221eda4e5ee04d230cbdb63f80aa9098e87381cf75b4a6f732c4dbc
3
+ metadata.gz: 625ce68b5e4d109bc1ddc27921ba6fc52d0d27fab2b23b9ebed9f0af92d1a523
4
+ data.tar.gz: '08302ed91e755eea56d05d7d1fb7d30403929f7cb943e7042b0ae43ecfb137f6'
5
5
  SHA512:
6
- metadata.gz: 267422c819129ea1e6eca8cc66ef95448345f3278cdd2ee036cc04303c8b9ef3628757808c9edc2dae815f30d56b9dceafa10670f0a60b492cb8c1df9e5254cf
7
- data.tar.gz: 30566b29367c5991e4e6229c98f85f217467f8cbd7dd15c03a3f8f270c11da6d2439a699e9133f707d0b4a256f38e611a83e32774decbe4f35fa09647fde7d78
6
+ metadata.gz: 15b5b10a2edd73c90f01a3e803dceee6f2afccf38c2810b4e70327f5b88ffa6d0d0ee4570e5aa190fa6483fcd3d0ee34924b391b4e390ccba2b4ca86319493e4
7
+ data.tar.gz: 50d4c0c8f6059ed88b66b08d6c4ccbe6e795087ffee0bc5a3fc45327ddacc750178317c355a8e742f0aa2f0d4024b3ce19c00bc9e5eed4408ef20470211f387b
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)
@@ -57,7 +57,7 @@ module ERBLint
57
57
 
58
58
  def possible_attribute_values(tag, attr_name)
59
59
  value = tag.attributes[attr_name]&.value || nil
60
- basic_conditional_code_check(value || "") || [value].compact
60
+ [value].compact
61
61
  end
62
62
 
63
63
  # Map possible values from condition
@@ -0,0 +1,36 @@
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, and don't format it like an ID. Additionally, `aria-label` should be concise and should not contain line breaks."
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
+
27
+ if (aria_label.start_with?(/^[a-z]/) || aria_label.match?(/[\r\n]+/)) && !@config.exceptions.include?(aria_label)
28
+ generate_offense(self.class, processed_source, tag)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ 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.1
4
+ version: 0.3.1
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-18 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