diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..7b3eb46 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: bundler + directory: "/" + schedule: + interval: weekly + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly diff --git a/.github/workflows/accessibility-alt-text-bot.yml b/.github/workflows/accessibility-alt-text-bot.yml new file mode 100644 index 0000000..4b3c2b3 --- /dev/null +++ b/.github/workflows/accessibility-alt-text-bot.yml @@ -0,0 +1,26 @@ +name: Accessibility-alt-text-bot +on: + issues: + types: [opened, edited] + pull_request: + types: [opened, edited] + issue_comment: + types: [created, edited] + discussion: + types: [created, edited] + discussion_comment: + types: [created, edited] + +permissions: + issues: write + pull-requests: write + discussions: write + +jobs: + accessibility_alt_text_bot: + name: Check alt text is set on issue or pull requests + runs-on: ubuntu-latest + if: ${{ github.event.issue || github.event.pull_request || github.event.discussion }} + steps: + - name: Get action 'github/accessibility-alt-text-bot' + uses: github/accessibility-alt-text-bot@v1.2.0 diff --git a/.rubocop.yml b/.rubocop.yml index 7edaeb1..63ae720 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -8,3 +8,6 @@ AllCops: Style/Documentation: Enabled: false + +Gemspec/DevelopmentDependencies: + EnforcedStyle: gemspec diff --git a/Gemfile.lock b/Gemfile.lock index 2b54584..eecdbe3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,18 +1,18 @@ PATH remote: . specs: - erblint-github (0.3.1) + erblint-github (0.4.0) GEM remote: https://rubygems.org/ specs: - actionview (7.0.4.2) - activesupport (= 7.0.4.2) + actionview (7.0.5) + activesupport (= 7.0.5) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activesupport (7.0.4.2) + activesupport (7.0.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -26,9 +26,9 @@ GEM parser (>= 2.4) smart_properties builder (3.2.4) - concurrent-ruby (1.2.0) + concurrent-ruby (1.2.2) crass (1.0.6) - erb_lint (0.3.1) + erb_lint (0.4.0) activesupport better_html (>= 2.0.1) parser (>= 2.7.1.4) @@ -36,34 +36,35 @@ GEM rubocop smart_properties erubi (1.12.0) - i18n (1.12.0) + i18n (1.13.0) concurrent-ruby (~> 1.0) json (2.6.3) - loofah (2.19.1) + loofah (2.21.3) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mini_portile2 (2.8.1) + nokogiri (>= 1.12.0) + mini_portile2 (2.8.2) minitest (5.18.0) mocha (2.0.2) ruby2_keywords (>= 0.0.5) - nokogiri (1.14.0) - mini_portile2 (~> 2.8.0) + nokogiri (1.15.2) + mini_portile2 (~> 2.8.2) racc (~> 1.4) - parallel (1.22.1) - parser (3.2.2.0) + parallel (1.23.0) + parser (3.2.2.1) ast (~> 2.4.1) racc (1.6.2) rack (3.0.4.1) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.5.0) - loofah (~> 2.19, >= 2.19.1) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) rainbow (3.1.1) rake (13.0.6) - regexp_parser (2.7.0) + regexp_parser (2.8.0) rexml (3.2.5) - rubocop (1.49.0) + rubocop (1.52.0) json (~> 2.3) parallel (~> 1.10) parser (>= 3.2.0.0) @@ -73,7 +74,7 @@ GEM rubocop-ast (>= 1.28.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.28.0) + rubocop-ast (1.29.0) parser (>= 3.2.1.0) rubocop-github (0.20.0) rubocop (>= 1.37) @@ -89,7 +90,7 @@ GEM ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) smart_properties (1.17.0) - tzinfo (2.0.5) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) @@ -97,12 +98,12 @@ PLATFORMS ruby DEPENDENCIES - erb_lint (~> 0.3.0) + erb_lint (~> 0.4.0) erblint-github! minitest (~> 5.18.0) mocha (~> 2.0.2) rake (~> 13.0.6) - rubocop (= 1.49.0) + rubocop (= 1.52.0) rubocop-github (~> 0.20.0) BUNDLED WITH diff --git a/README.md b/README.md index 597f023..eb4b51d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # erblint-github + Template style checking for GitHub's Ruby projects ## Setup @@ -10,49 +11,19 @@ gem "erb_lint", require: false gem "erblint-github" ``` -2. Require the linters within the `.erb-linters` folder. This could be done by adding a file `.erb-linters/erblint-github.rb` with the following line. +2. Require the lint rules from this library. Currently, the only supported way is to add a new file in `.erb-linters/erblint-github.rb` with the line: ```ruby require "erblint-github/linters" ``` -3. Update the `erb-lint.yml` to configure the rule. - -### .erb-lint.yml +3. Update your `erb-lint.yml` to pull in our recommended configs. This will ensure you are up-to-date with our recommendations. -```yaml +```yaml --- -linters: - GitHub::Accessibility::AriaLabelIsWellFormatted: - enabled: true - GitHub::Accessibility::AvoidBothDisabledAndAriaDisabled: - enabled: true - GitHub::Accessibility::AvoidGenericLinkText: - enabled: true - GitHub::Accessibility::DisabledAttribute: - enabled: true - GitHub::Accessibility::IframeHasTitle: - enabled: true - GitHub::Accessibility::ImageHasAlt: - enabled: true - GitHub::Accessibility::NavigationHasLabel: - enabled: true - GitHub::Accessibility::LinkHasHref: - enabled: true - GitHub::Accessibility::NestedInteractiveElements: - enabled: true - GitHub::Accessibility::NoAriaHiddenOnFocusable: - enabled: true - GitHub::Accessibility::NoAriaLabelMisuse: - enabled: true - GitHub::Accessibility::NoPositiveTabIndex: - enabled: true - GitHub::Accessibility::NoRedundantImageAlt: - enabled: true - GitHub::Accessibility::NoTitleAttribute: - enabled: true - GitHub::Accessibility::SvgHasAccessibleText: - enabled: true +inherit_gem: + erblint-github: + - config/accessibility.yml ``` ## Rules @@ -73,34 +44,6 @@ linters: - [GitHub::Accessibility::NoTitleAttribute](./docs/rules/accessibility/no-title-attribute.md) - [GitHub::Accessibility::SvgHasAccessibleText](./docs/rules/accessibility/svg-has-accessible-text.md) -## Disabling a rule (Deprecated) - -_This is a soon-to-be deprecated feature. Do not use. See [migration guide](./docs/counter-migration-guide.md)_ - -`erblint` does not natively support rule disables. At GitHub, we've implemented these rules in a way to allow rules to be disabled at an offense-level via counters or disabled at a file-level because often times, we want to enable a rule but aren't able to address all offenses at once. We achieve this in one of two ways. - -Rules that are marked as `Counter` can be disabled by adding a comment with the offense count that matches the number of offenses within the file like: - -```.html.erb -<%# erblint:counter GitHub::Accessibility::LinkHasHrefCounter 1 %> -``` - -In this comment example, when a new `LinkHasHref` offense has been added, the counter will need to be bumped up to 2. More recent rules use a `Counter` format. - -If you are enabling a rule for the first time and your codebase has a lot of offenses, you can use the `-a` command to automatically add these counter comments in the appropriate places. - -``` -bundle exec erblint app/views app/components -a -``` - -Rules that are not marked as `Counter` like `NoRedundantImageAlt` are considered to be legacy format. We are in the process of migrating these to counters. These rules can still be disabled at the file-level by adding this comment at the top of the file: - -```.html.erb -<%# erblint:disable GitHub::Accessibility::NoRedundantImageAlt %> -``` - -However, unlike a counter, any subsequent offenses introduced to the file will not raise. - ## Testing ``` diff --git a/config/accessibility.yml b/config/accessibility.yml new file mode 100644 index 0000000..e55a2cb --- /dev/null +++ b/config/accessibility.yml @@ -0,0 +1,32 @@ +--- +linters: + GitHub::Accessibility::AriaLabelIsWellFormatted: + enabled: true + GitHub::Accessibility::AvoidBothDisabledAndAriaDisabled: + enabled: true + GitHub::Accessibility::AvoidGenericLinkText: + enabled: true + GitHub::Accessibility::DisabledAttribute: + enabled: true + GitHub::Accessibility::IframeHasTitle: + enabled: true + GitHub::Accessibility::ImageHasAlt: + enabled: true + GitHub::Accessibility::NavigationHasLabel: + enabled: true + GitHub::Accessibility::LinkHasHref: + enabled: true + GitHub::Accessibility::NestedInteractiveElements: + enabled: true + GitHub::Accessibility::NoAriaHiddenOnFocusable: + enabled: true + GitHub::Accessibility::NoAriaLabelMisuse: + enabled: true + GitHub::Accessibility::NoPositiveTabIndex: + enabled: true + GitHub::Accessibility::NoRedundantImageAlt: + enabled: true + GitHub::Accessibility::NoTitleAttribute: + enabled: true + GitHub::Accessibility::SvgHasAccessibleText: + enabled: true diff --git a/docs/counter-migration-guide.md b/docs/counter-migration-guide.md index 8733cea..d92626c 100644 --- a/docs/counter-migration-guide.md +++ b/docs/counter-migration-guide.md @@ -1,5 +1,7 @@ # Counter migration guide +This is relevant for `erblint-github` versions <= 0.3.2. + [ERBLint v0.4.0](https://github.com/Shopify/erb-lint/releases/tag/v0.4.0) introduces support for inline lint rule disables. Since an inline disable feature is now natively available, it is time to move away from the in-house (hacky) counter system we've used internally over the years and in this library. 🎉 diff --git a/docs/rules/accessibility/aria-label-is-well-formatted.md b/docs/rules/accessibility/aria-label-is-well-formatted.md index 90b4a67..ff310d5 100644 --- a/docs/rules/accessibility/aria-label-is-well-formatted.md +++ b/docs/rules/accessibility/aria-label-is-well-formatted.md @@ -48,7 +48,7 @@ If you determine that there are valid scenarios for `aria-label` to start with l ``` ```erb - aria-label="github.com/shopify/erb-lint"> + ``` ### **Correct** code for this rule 👍 @@ -62,5 +62,5 @@ If you determine that there are valid scenarios for `aria-label` to start with l ```` ```erb - aria-label="Shopify/erb-lint on GitHub"> + ``` diff --git a/erblint-github.gemspec b/erblint-github.gemspec index 2aa3d55..0fc6c4d 100644 --- a/erblint-github.gemspec +++ b/erblint-github.gemspec @@ -2,13 +2,13 @@ Gem::Specification.new do |s| s.name = "erblint-github" - s.version = "0.3.1" + s.version = "0.4.0" s.summary = "erblint GitHub" s.description = "Template style checking for GitHub Ruby repositories" s.homepage = "https://github.com/github/erblint-github" s.license = "MIT" - s.files = Dir["README.md", "LICENSE", "lib/**/*"] + s.files = Dir["README.md", "LICENSE", "lib/**/*", "config/**/*"] s.require_paths = ["lib"] s.required_ruby_version = ">= 2.7.0" @@ -16,12 +16,12 @@ Gem::Specification.new do |s| s.email = ["opensource+erblint-github@github.com"] s.authors = ["GitHub Open Source"] - s.add_development_dependency "erb_lint", "~> 0.3.0" + s.add_development_dependency "erb_lint", "~> 0.4.0" s.add_development_dependency "minitest", "~> 5.18.0" s.add_development_dependency "mocha", "~> 2.0.2" s.add_development_dependency "rake", "~> 13.0.6" - s.add_development_dependency "rubocop", "= 1.49.0" + s.add_development_dependency "rubocop", "= 1.52.0" s.add_development_dependency "rubocop-github", "~> 0.20.0" s.metadata["rubygems_mfa_required"] = "true" end diff --git a/lib/erblint-github/linters/custom_helpers.rb b/lib/erblint-github/linters/custom_helpers.rb index 24826ea..8563a59 100644 --- a/lib/erblint-github/linters/custom_helpers.rb +++ b/lib/erblint-github/linters/custom_helpers.rb @@ -8,39 +8,6 @@ module Linters module CustomHelpers INTERACTIVE_ELEMENTS = %w[button summary input select textarea a].freeze - def counter_correct?(processed_source) - comment_node = nil - expected_count = 0 - rule_name = simple_class_name - offenses_count = @offenses.length - - processed_source.parser.ast.descendants(:erb).each do |node| - indicator_node, _, code_node, = *node - indicator = indicator_node&.loc&.source - comment = code_node&.loc&.source&.strip - - if indicator == "#" && comment.start_with?("erblint:counter") && comment.match(rule_name) - comment_node = node - expected_count = comment.match(/\s(\d+)\s?$/)[1].to_i - end - end - - if offenses_count.zero? - # have to adjust to get `\n` so we delete the whole line - add_offense(processed_source.to_source_range(comment_node.loc.adjust(end_pos: 1)), "Unused erblint:counter comment for #{rule_name}", "") if comment_node - return - end - - first_offense = @offenses[0] - - if comment_node.nil? - 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} %>") - else - clear_offenses - 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 - end - end - def generate_offense(klass, processed_source, tag, message = nil, replacement = nil) message ||= klass::MESSAGE message += "\nLearn more at https://github.com/github/erblint-github#rules.\n" diff --git a/lib/erblint-github/linters/github/accessibility/avoid_both_disabled_and_aria_disabled.rb b/lib/erblint-github/linters/github/accessibility/avoid_both_disabled_and_aria_disabled.rb index 56324e7..25d4e74 100644 --- a/lib/erblint-github/linters/github/accessibility/avoid_both_disabled_and_aria_disabled.rb +++ b/lib/erblint-github/linters/github/accessibility/avoid_both_disabled_and_aria_disabled.rb @@ -13,11 +13,6 @@ class AvoidBothDisabledAndAriaDisabled < Linter ELEMENTS_WITH_NATIVE_DISABLED_ATTRIBUTE_SUPPORT = %w[button fieldset input optgroup option select textarea].freeze MESSAGE = "[aria-disabled] may be used in place of native HTML [disabled] to allow tab-focus on an otherwise ignored element. Setting both attributes is contradictory." - class ConfigSchema < LinterConfig - property :counter_enabled, accepts: [true, false], default: false, reader: :counter_enabled? - end - self.config_schema = ConfigSchema - def run(processed_source) tags(processed_source).each do |tag| next if tag.closing? @@ -26,10 +21,6 @@ def run(processed_source) generate_offense(self.class, processed_source, tag) end - - if @config.counter_enabled? - counter_correct?(processed_source) - end end end end diff --git a/lib/erblint-github/linters/github/accessibility/avoid_generic_link_text.rb b/lib/erblint-github/linters/github/accessibility/avoid_generic_link_text.rb index 9d24c6b..ac24f73 100644 --- a/lib/erblint-github/linters/github/accessibility/avoid_generic_link_text.rb +++ b/lib/erblint-github/linters/github/accessibility/avoid_generic_link_text.rb @@ -22,11 +22,6 @@ class AvoidGenericLinkText < Linter MESSAGE = "Avoid using generic link text such as #{BANNED_GENERIC_TEXT.join(', ')} which do not make sense in isolation." - class ConfigSchema < LinterConfig - property :counter_enabled, accepts: [true, false], default: false, reader: :counter_enabled? - end - self.config_schema = ConfigSchema - def run(processed_source) processed_source.ast.children.each_with_index do |node, index| next unless node.methods.include?(:type) && node.type == :text @@ -98,9 +93,6 @@ def run(processed_source) banned_text = nil end end - if @config.counter_enabled? - counter_correct?(processed_source) - end end private diff --git a/lib/erblint-github/linters/github/accessibility/disabled_attribute.rb b/lib/erblint-github/linters/github/accessibility/disabled_attribute.rb index 6ad9fda..475efca 100644 --- a/lib/erblint-github/linters/github/accessibility/disabled_attribute.rb +++ b/lib/erblint-github/linters/github/accessibility/disabled_attribute.rb @@ -13,16 +13,6 @@ class DisabledAttribute < Linter VALID_DISABLED_TAGS = %w[button input textarea option select fieldset optgroup task-lists].freeze MESSAGE = "`disabled` is only valid on #{VALID_DISABLED_TAGS.join(', ')}." - class ConfigSchema < LinterConfig - property :counter_enabled, accepts: [true, false], default: false, reader: :counter_enabled? - end - self.config_schema = ConfigSchema - - class ConfigSchema < LinterConfig - property :counter_enabled, accepts: [true, false], default: false, reader: :counter_enabled? - end - self.config_schema = ConfigSchema - def run(processed_source) tags(processed_source).each do |tag| next if tag.closing? @@ -31,10 +21,6 @@ def run(processed_source) generate_offense(self.class, processed_source, tag) end - - if @config.counter_enabled? - counter_correct?(processed_source) - end end end end diff --git a/lib/erblint-github/linters/github/accessibility/iframe_has_title.rb b/lib/erblint-github/linters/github/accessibility/iframe_has_title.rb index 74af566..6cf6a45 100644 --- a/lib/erblint-github/linters/github/accessibility/iframe_has_title.rb +++ b/lib/erblint-github/linters/github/accessibility/iframe_has_title.rb @@ -13,11 +13,6 @@ class IframeHasTitle < Linter MESSAGE = "`