a11y-lint 0.13.0 → 0.14.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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c80dbcc5dec24d2850b42b84b2bbf512dc792f9c77e41ba4fd778d792c0d750a
|
|
4
|
+
data.tar.gz: aff2c4e3002a785f2f8fbfc5cfe9b115466cc3850299114b8724a82b5c71e52a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c6431784a0c4704f7040953c2ef881678b13e61fee513f639c1ff4de019a4bb1599633638902764dc0cf9f9b25fe553349262639e0f30029033e5498f252f23a
|
|
7
|
+
data.tar.gz: 5b140955d0e2eadc1fefe2314bf85a16f0129d0c2cf569deb507c829ca0cf1aeb633ed601d670e4eef814d1b825a0576a5ad5d41e733bf4c8fceae7b6040f4fe
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.14.0] - 2026-04-28
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Breaking:** `SimpleFormSelectMissingAccessibleName` is now `SimpleFormInputMissingAccessibleName` and flags any Simple Form `form.input` with `label: false`/`label: ""` that has no `aria-label` or `aria-labelledby` in `input_html`, regardless of input type (WCAG 4.1.2). `as: :hidden` is skipped. Projects that pinned the rule by name in `.a11y-lint.yml` need to update the key
|
|
15
|
+
|
|
10
16
|
## [0.13.0] - 2026-04-28
|
|
11
17
|
|
|
12
18
|
### Added
|
|
@@ -29,15 +29,19 @@ In Simple Form, both go inside `input_html`:
|
|
|
29
29
|
|
|
30
30
|
A placeholder is **not** a label. It disappears as soon as the user types, browsers don't reliably expose it as the accessible name, and it fails users who rely on the prompt staying visible while they fill the field.
|
|
31
31
|
|
|
32
|
-
##
|
|
33
|
-
{:#simple-form-
|
|
32
|
+
## SimpleFormInputMissingAccessibleName
|
|
33
|
+
{:#simple-form-input-missing-accessible-name}
|
|
34
34
|
|
|
35
|
-
Applies to: Simple Form `form.input` calls
|
|
35
|
+
Applies to: Simple Form `form.input` calls with `label: false` or `label: ""` — regardless of input type. `as: :hidden` is skipped, since hidden inputs don't render a visible control.
|
|
36
36
|
|
|
37
37
|
The rule passes when `input_html` provides `aria-label` or `aria-labelledby`. Both hash and string keys are accepted (`aria: { label: "..." }` and `"aria-label" => "..."`).
|
|
38
38
|
|
|
39
39
|
### Bad
|
|
40
40
|
|
|
41
|
+
```erb
|
|
42
|
+
<%%= form.input :name, label: false %>
|
|
43
|
+
```
|
|
44
|
+
|
|
41
45
|
```erb
|
|
42
46
|
<%%= form.input :sort_by, collection: opts, label: false %>
|
|
43
47
|
```
|
|
@@ -48,17 +52,18 @@ The rule passes when `input_html` provides `aria-label` or `aria-labelledby`. Bo
|
|
|
48
52
|
|
|
49
53
|
### Good
|
|
50
54
|
|
|
51
|
-
Render a visible label by removing `label: false
|
|
55
|
+
Render a visible label by removing `label: false` and letting Simple Form generate one from the attribute name, or by passing an explicit string:
|
|
52
56
|
|
|
53
57
|
```erb
|
|
58
|
+
<%%= form.input :name %>
|
|
54
59
|
<%%= form.input :sort_by, collection: opts, label: "Sort by" %>
|
|
55
60
|
```
|
|
56
61
|
|
|
57
62
|
Or, when there's no visible label, supply `aria-label`:
|
|
58
63
|
|
|
59
64
|
```erb
|
|
60
|
-
<%%= form.input :
|
|
61
|
-
input_html: { aria: { label: "
|
|
65
|
+
<%%= form.input :name, label: false,
|
|
66
|
+
input_html: { aria: { label: "Name" } } %>
|
|
62
67
|
```
|
|
63
68
|
|
|
64
69
|
Or `aria-labelledby` pointing to existing visible text:
|
|
@@ -69,19 +74,25 @@ Or `aria-labelledby` pointing to existing visible text:
|
|
|
69
74
|
input_html: { aria: { labelledby: "sort-label" } } %>
|
|
70
75
|
```
|
|
71
76
|
|
|
77
|
+
`as: :hidden` doesn't render a visible control, so it's exempt:
|
|
78
|
+
|
|
79
|
+
```erb
|
|
80
|
+
<%%= form.input :secret, as: :hidden, label: false %>
|
|
81
|
+
```
|
|
82
|
+
|
|
72
83
|
### Slim equivalent
|
|
73
84
|
|
|
74
85
|
```slim
|
|
75
|
-
= form.input :
|
|
86
|
+
= form.input :name, label: false, input_html: { aria: { label: "Name" } }
|
|
76
87
|
```
|
|
77
88
|
|
|
78
89
|
## What this rule doesn't catch
|
|
79
90
|
|
|
80
91
|
This rule has a deliberately narrow scope. Things it doesn't flag:
|
|
81
92
|
|
|
82
|
-
- **Plain
|
|
93
|
+
- **Plain HTML form controls.** The rule targets Simple Form's `form.input` helper. A bare `<input>`, `<select>`, or `<textarea>` with no associated `<label>` is not reported.
|
|
83
94
|
- **Other Simple Form helpers.** `form.select`, `form.association`, and similar helpers aren't checked — only `form.input`.
|
|
84
|
-
- **
|
|
95
|
+
- **Inputs without `label: false`.** Simple Form auto-generates a label from the attribute name, so `form.input :name` is treated as having a visible label. The rule only kicks in once the label is explicitly suppressed.
|
|
85
96
|
- **Phlex views.** The rule is a no-op in Phlex by design. The Phlex pipeline only walks receiverless calls, so `form.input(...)` isn't surfaced as a candidate node. Simple Form code embedded inside a Phlex component won't be checked.
|
|
86
97
|
- **Bad accessible name content.** `aria: { label: "" }` will pass the rule check above (an empty aria-label is its own problem, but not this rule's). `aria: { label: "select" }` will pass. The linter checks that an aria attribute is present, not that the value is useful.
|
|
87
98
|
- **Dynamic accessible names.** `aria: { label: variable }` satisfies the rule even if `variable` is `nil` at runtime.
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
module A11y
|
|
4
4
|
module Lint
|
|
5
5
|
module Rules
|
|
6
|
-
# Checks that Simple Form `form.input` calls
|
|
7
|
-
# (via `collection:` or `as: :select`) with `label: false` /
|
|
6
|
+
# Checks that Simple Form `form.input` calls with `label: false` /
|
|
8
7
|
# `label: ""` provide an accessible name through `input_html:`
|
|
9
|
-
# `aria-label` or `aria-labelledby` (WCAG 4.1.2).
|
|
10
|
-
|
|
8
|
+
# `aria-label` or `aria-labelledby` (WCAG 4.1.2). Skips
|
|
9
|
+
# `as: :hidden`, which doesn't render a visible control.
|
|
10
|
+
class SimpleFormInputMissingAccessibleName < NodeRule
|
|
11
11
|
def check
|
|
12
12
|
return if no_offense?
|
|
13
13
|
|
|
@@ -18,14 +18,13 @@ module A11y
|
|
|
18
18
|
|
|
19
19
|
def no_offense?
|
|
20
20
|
!helper_call ||
|
|
21
|
-
!select_like? ||
|
|
22
21
|
!helper_call.label_hidden? ||
|
|
22
|
+
hidden_input? ||
|
|
23
23
|
aria_label_in_input_html?
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def
|
|
27
|
-
helper_call.
|
|
28
|
-
helper_call.keyword_symbol?(:as, :select)
|
|
26
|
+
def hidden_input?
|
|
27
|
+
helper_call.keyword_symbol?(:as, :hidden)
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def aria_label_in_input_html?
|
|
@@ -53,7 +52,7 @@ module A11y
|
|
|
53
52
|
|
|
54
53
|
def offense_message
|
|
55
54
|
<<~MSG.strip
|
|
56
|
-
form.input
|
|
55
|
+
form.input missing an accessible name \
|
|
57
56
|
requires aria-label or aria-labelledby in input_html (WCAG 4.1.2)
|
|
58
57
|
MSG
|
|
59
58
|
end
|
data/lib/a11y/lint/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Abdullah Hashim
|
|
@@ -124,7 +124,7 @@ files:
|
|
|
124
124
|
- lib/a11y/lint/rules/robust/button_missing_accessible_name.rb
|
|
125
125
|
- lib/a11y/lint/rules/robust/button_tag_missing_accessible_name.rb
|
|
126
126
|
- lib/a11y/lint/rules/robust/link_to_missing_accessible_name.rb
|
|
127
|
-
- lib/a11y/lint/rules/robust/
|
|
127
|
+
- lib/a11y/lint/rules/robust/simple_form_input_missing_accessible_name.rb
|
|
128
128
|
- lib/a11y/lint/slim_node.rb
|
|
129
129
|
- lib/a11y/lint/slim_runner.rb
|
|
130
130
|
- lib/a11y/lint/version.rb
|