a11y-lint 0.3.1 → 0.4.0

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: 5c000b195d8308dc83a3480df00e9a469e064535305ece969f779ee05b93fc87
4
- data.tar.gz: cf3ec59befbf3057ff5f1a9d971925656fbf0f0c001e40780202abd862bd67a2
3
+ metadata.gz: df2381933d808c2694937750b55b63897d22feb8b3726e8635504afa6bcb320b
4
+ data.tar.gz: 5b04343e74f0ebb363cb2b2c065d67b9b20398d4b5bd12e86e89fe38a7bcfa8d
5
5
  SHA512:
6
- metadata.gz: ad3e23e799fce7418f9e28224a9ec63120f42d5a04bd27710637df12e278118728af0a3baf47c5fe8b3cfa2a12e6bfbc366d8f334a453b385111b1befc2828df
7
- data.tar.gz: 8be4c61819523edcbb0a11bb4959ab5834b0552d0fe27be2fc71aa30362dc18eb5ca8f9d25bffa5578f7f77d0af11b5e1716e8429b4c2a865fcd3a243031ede0
6
+ metadata.gz: 4a71a89a925316ae52107958bed1cdc927d653ccc0425b81ad2bca612f694cdc63b52d9c277f24c1957976e5972ed5c810b831f150c353393014908e7e187a6d
7
+ data.tar.gz: d9982d126da0a7f412d8d43b68e90b27fcde739a3b08c2b6cc0e948241eb18b95e9e42542e5bb7ce75048f389fec11351901da0e900076369c3889d1e8c16b0a
data/.rubocop.yml CHANGED
@@ -6,3 +6,7 @@ Style/StringLiterals:
6
6
 
7
7
  Style/StringLiteralsInInterpolation:
8
8
  EnforcedStyle: double_quotes
9
+
10
+ Metrics/ClassLength:
11
+ Exclude:
12
+ - "test/**/*"
data/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2026-03-27
11
+
12
+ ### Added
13
+
14
+ - ERB template support: scans `.erb` files using Nokogiri for HTML parsing
15
+ - Both `ImgMissingAlt` and `ImageTagMissingAlt` rules now work on ERB templates
16
+ - CLI automatically detects and routes `.slim` and `.erb` files to the appropriate runner
17
+
18
+ ### Changed
19
+
20
+ - **Breaking:** `Runner` has been renamed to `SlimRunner`
21
+
10
22
  ## [0.3.1] - 2026-03-27
11
23
 
12
24
  ### Fixed
data/CLAUDE.md CHANGED
@@ -19,8 +19,11 @@ a11y-lint is a Ruby gem (v0.1.0) for accessibility linting. It uses the `A11y::L
19
19
 
20
20
  ## Architecture
21
21
 
22
- - **CLI:** `lib/a11y/lint/cli.rb` — command-line interface; executable at `exe/a11y-lint`
22
+ - **CLI:** `lib/a11y/lint/cli.rb` — command-line interface; executable at `exe/a11y-lint`; routes `.slim` files to `SlimRunner` and `.erb` files to `ErbRunner`
23
23
  - **Entry point:** `lib/a11y/lint.rb` — defines the `A11y::Lint` module and `A11y::Lint::Error` exception
24
+ - **Slim pipeline:** `SlimRunner` parses Slim templates via `Slim::Parser`; `Node` wraps Slim S-expressions
25
+ - **ERB pipeline:** `ErbRunner` parses ERB templates via Nokogiri; `ErbNode` wraps Nokogiri nodes and extracted `<%= %>` Ruby code
26
+ - **Rules:** `lib/a11y/lint/rules/` — rules implement `check(node)` against the shared node interface (`tag_name`, `attribute?`, `attributes`, `ruby_code`, `line`)
24
27
  - **Version:** `lib/a11y/lint/version.rb`
25
28
  - **Type signatures (RBS):** `sig/a11y/lint.rbs`
26
29
  - **Tests:** `test/` directory using Minitest; test helper at `test/test_helper.rb`
data/README.md CHANGED
@@ -33,7 +33,7 @@ a11y-lint app/views/
33
33
  a11y-lint app/views/home.html.slim app/views/about.html.slim
34
34
  ```
35
35
 
36
- With no arguments, it scans the current directory recursively for `.slim` files:
36
+ With no arguments, it scans the current directory recursively for `.slim` and `.erb` files:
37
37
 
38
38
  ```bash
39
39
  a11y-lint
@@ -45,7 +45,7 @@ a11y-lint
45
45
  require "a11y/lint"
46
46
 
47
47
  source = File.read("app/views/home.html.slim")
48
- runner = A11y::Lint::Runner.new([A11y::Lint::Rules::ImgMissingAlt.new])
48
+ runner = A11y::Lint::SlimRunner.new([A11y::Lint::Rules::ImgMissingAlt.new])
49
49
  offenses = runner.run(source, filename: "app/views/home.html.slim")
50
50
 
51
51
  offenses.each do |offense|
data/lib/a11y/lint/cli.rb CHANGED
@@ -17,7 +17,7 @@ module A11y
17
17
  files = resolve_files(@argv)
18
18
 
19
19
  if files.empty?
20
- @stderr.puts("No .slim files found")
20
+ @stderr.puts("No .slim or .erb files found")
21
21
  return 0
22
22
  end
23
23
 
@@ -56,7 +56,7 @@ module A11y
56
56
 
57
57
  def expand_path(path)
58
58
  if File.directory?(path)
59
- Dir.glob(File.join(path, "**", "*.slim"))
59
+ Dir.glob(File.join(path, "**", "*.{slim,erb}"))
60
60
  elsif File.file?(path)
61
61
  [path]
62
62
  else
@@ -66,10 +66,13 @@ module A11y
66
66
  end
67
67
 
68
68
  def lint_files(files)
69
- runner = Runner.new(all_rules)
69
+ rules = all_rules
70
+ slim_runner = SlimRunner.new(rules)
71
+ erb_runner = ErbRunner.new(rules)
70
72
 
71
73
  files.flat_map do |file|
72
74
  source = File.read(file)
75
+ runner = file.end_with?(".erb") ? erb_runner : slim_runner
73
76
  runner.run(source, filename: file)
74
77
  end
75
78
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module A11y
4
+ module Lint
5
+ # Wraps a Nokogiri node or extracted ERB output tag as a queryable node for lint rules.
6
+ class ErbNode
7
+ attr_reader :line
8
+
9
+ def initialize(line:, nokogiri_node: nil, ruby_code: nil)
10
+ @nokogiri_node = nokogiri_node
11
+ @ruby_code_string = ruby_code
12
+ @line = line
13
+ end
14
+
15
+ def tag_name
16
+ @nokogiri_node&.name
17
+ end
18
+
19
+ def attribute?(name)
20
+ attributes.key?(name)
21
+ end
22
+
23
+ def attributes
24
+ @attributes ||= extract_attributes
25
+ end
26
+
27
+ def ruby_code
28
+ @ruby_code_string
29
+ end
30
+
31
+ private
32
+
33
+ def extract_attributes
34
+ return {} unless @nokogiri_node
35
+
36
+ @nokogiri_node.attributes.each_with_object({}) do |(name, _attr), result|
37
+ result[name] = true
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+
5
+ module A11y
6
+ module Lint
7
+ # Parses ERB templates and checks them against accessibility rules.
8
+ class ErbRunner
9
+ ERB_TAG = /<%.*?%>/m
10
+ ERB_OUTPUT_TAG = /<%=\s*(.*?)\s*-?%>/m
11
+
12
+ def initialize(rules)
13
+ @rules = rules
14
+ end
15
+
16
+ def run(source, filename:)
17
+ @filename = filename
18
+ @offenses = []
19
+
20
+ check_html_nodes(source)
21
+ check_erb_output_tags(source)
22
+
23
+ @offenses
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :rules
29
+
30
+ def check_html_nodes(source)
31
+ html = source.gsub(ERB_TAG, "")
32
+ doc = Nokogiri::HTML4::DocumentFragment.parse(html)
33
+
34
+ doc.traverse do |nokogiri_node|
35
+ next unless nokogiri_node.element?
36
+
37
+ node = ErbNode.new(nokogiri_node: nokogiri_node, line: nokogiri_node.line)
38
+ check_node(node)
39
+ end
40
+ end
41
+
42
+ def check_erb_output_tags(source)
43
+ source.scan(ERB_OUTPUT_TAG) do
44
+ match = Regexp.last_match
45
+ code = match[1]
46
+ line_number = source[0...match.begin(0)].count("\n") + 1
47
+ node = ErbNode.new(ruby_code: code, line: line_number)
48
+ check_node(node)
49
+ end
50
+ end
51
+
52
+ def check_node(node)
53
+ rules.each do |rule|
54
+ message = rule.check(node)
55
+ next unless message
56
+
57
+ @offenses << Offense.new(
58
+ rule: rule.name,
59
+ filename: @filename,
60
+ line: node.line,
61
+ message: message
62
+ )
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -3,7 +3,7 @@
3
3
  module A11y
4
4
  module Lint
5
5
  # Parses Slim templates and checks them against accessibility rules.
6
- class Runner
6
+ class SlimRunner
7
7
  def initialize(rules)
8
8
  @rules = rules
9
9
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module A11y
4
4
  module Lint
5
- VERSION = "0.3.1"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
data/lib/a11y/lint.rb CHANGED
@@ -1,13 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "slim"
4
+ require "nokogiri"
4
5
  require_relative "lint/version"
5
6
  require_relative "lint/offense"
6
7
  require_relative "lint/node"
8
+ require_relative "lint/erb_node"
7
9
  require_relative "lint/rule"
8
10
  require_relative "lint/rules/image_tag_missing_alt"
9
11
  require_relative "lint/rules/img_missing_alt"
10
- require_relative "lint/runner"
12
+ require_relative "lint/slim_runner"
13
+ require_relative "lint/erb_runner"
11
14
 
12
15
  module A11y
13
16
  module Lint
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: a11y-lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdullah Hashim
@@ -9,6 +9,20 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: nokogiri
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '1.13'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '1.13'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: slim
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -42,12 +56,14 @@ files:
42
56
  - exe/a11y-lint
43
57
  - lib/a11y/lint.rb
44
58
  - lib/a11y/lint/cli.rb
59
+ - lib/a11y/lint/erb_node.rb
60
+ - lib/a11y/lint/erb_runner.rb
45
61
  - lib/a11y/lint/node.rb
46
62
  - lib/a11y/lint/offense.rb
47
63
  - lib/a11y/lint/rule.rb
48
64
  - lib/a11y/lint/rules/image_tag_missing_alt.rb
49
65
  - lib/a11y/lint/rules/img_missing_alt.rb
50
- - lib/a11y/lint/runner.rb
66
+ - lib/a11y/lint/slim_runner.rb
51
67
  - lib/a11y/lint/version.rb
52
68
  - sig/a11y/lint.rbs
53
69
  homepage: https://github.com/Guided-Rails/a11y-lint