feat(html): port useValidAriaValues a11y rule to HTML#9928
Conversation
Ports the useValidAriaValues lint rule from JSX to HTML, as part of the umbrella issue biomejs#8155. The rule validates that aria-* attribute values match the expected types defined by the WAI-ARIA specification: - Boolean (true/false) - Tristate (true/false/mixed) - Integer, Number - Token, TokenList (enumerated values) - IdReference, IdReferenceList - String Case-insensitive attribute name matching in .html files. Vue dynamic bindings (:aria-x, v-bind:aria-x) are skipped since values are runtime expressions. Includes HTML and Vue test fixtures (valid + invalid). Closes part of biomejs#8155. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🦋 Changeset detectedLatest commit: 9c0f9da The changes in this PR will be included in the next version bump. This PR includes changesets to release 14 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a new HTML accessibility lint rule Suggested reviewers
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.changeset/port-use-valid-aria-values-html.md:
- Line 5: Update the changeset text to link to the rule documentation and add a
tiny inline example: edit .changeset/port-use-valid-aria-values-html.md to
include a markdown link to the useValidAriaValues rule docs (e.g.,
"useValidAriaValues" -> [link]) and append a short HTML example showing an
invalid vs. corrected usage (e.g., an element with an invalid aria-* value and
the corrected value) so readers see the impact immediately.
In `@crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs`:
- Around line 108-150: Several diagnostic messages in the AriaValueType match
arms have grammar issues; update the user-facing strings in the match arms for
AriaValueType::Boolean, ::OptionalBoolean, ::Integer, ::Number, ::Tristate and
any similar literal messages used with diagnostic.footer_list or diagnostic.note
so they read correctly (e.g., "The only supported values for the
{attribute_name} property are one of the following:", "The only value supported
is a number without fractional components.", "The only supported value is a
number.", and "The only supported value for the {attribute_name} property is one
of the following:"); locate these messages in the AriaValueType match within
use_valid_aria_values.rs and replace the awkward phrasing ("is", "is number",
missing "is") with the corrected wording while keeping attribute_name
interpolation and existing helper calls (diagnostic.footer_list /
diagnostic.note) intact.
- Around line 84-95: The code currently short-circuits on valueless attributes
because html_attr.value()? returns None; update the logic in
use_valid_aria_values (where attribute_value, value_text and
aria_property.value_type() are used) to treat a missing value as the boolean
"true" (or otherwise normalize valueless aria-* to the equivalent string) before
checking aria_property.value_type().contains(&value_text), and add test fixtures
that include valueless aria attributes (e.g., invalid and valid HTML fixtures
exercising <div aria-hidden> and similar) to cover this case and document the
intended behavior; ensure UseValidAriaValuesState remains populated with
attribute_name and property_type as before.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b784b012-f52a-4103-ba49-ac9e568a823b
⛔ Files ignored due to path filters (4)
crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/invalid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/valid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/vue/invalid.vue.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/vue/valid.vue.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (6)
.changeset/port-use-valid-aria-values-html.mdcrates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rscrates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/invalid.htmlcrates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/valid.htmlcrates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/vue/invalid.vuecrates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/vue/valid.vue
| "@biomejs/biome": minor | ||
| --- | ||
|
|
||
| Ported the `useValidAriaValues` lint rule to HTML. This rule checks that all `aria-*` attribute values in HTML elements are valid according to the WAI-ARIA specification, including boolean, integer, token, and token list types. |
There was a problem hiding this comment.
Link the rule docs in the changeset (and add a tiny example).
Nice and concise, but for rule references this should link the rule documentation, and a brief inline example helps end users immediately see impact.
✍️ Proposed wording
-Ported the `useValidAriaValues` lint rule to HTML. This rule checks that all `aria-*` attribute values in HTML elements are valid according to the WAI-ARIA specification, including boolean, integer, token, and token list types.
+Ported [`useValidAriaValues`](https://biomejs.dev/linter/rules/use-valid-aria-values/) to HTML. Biome now validates static `aria-*` attribute values in HTML elements against WAI-ARIA types, catching invalid values such as `aria-hidden="yes"`.As per coding guidelines: "for rule references, include links to the rule documentation" and "include examples with inline code snippets or code blocks for new rules".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Ported the `useValidAriaValues` lint rule to HTML. This rule checks that all `aria-*` attribute values in HTML elements are valid according to the WAI-ARIA specification, including boolean, integer, token, and token list types. | |
| Ported [`useValidAriaValues`](https://biomejs.dev/linter/rules/use-valid-aria-values/) to HTML. Biome now validates static `aria-*` attribute values in HTML elements against WAI-ARIA types, catching invalid values such as `aria-hidden="yes"`. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.changeset/port-use-valid-aria-values-html.md at line 5, Update the
changeset text to link to the rule documentation and add a tiny inline example:
edit .changeset/port-use-valid-aria-values-html.md to include a markdown link to
the useValidAriaValues rule docs (e.g., "useValidAriaValues" -> [link]) and
append a short HTML example showing an invalid vs. corrected usage (e.g., an
element with an invalid aria-* value and the corrected value) so readers see the
impact immediately.
Merging this PR will not alter performance
Comparing Footnotes
|
- Handle valueless aria attributes (<div aria-hidden>) as 'true' per HTML spec
- Fix grammar in diagnostic messages ('values...is' -> 'values...are')
- Improve changeset with rule doc link and example
- Add valueless attribute test cases (valid + invalid)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Diagnostics now include pillar 3 (instruct user what to do):
'Use a valid value for the {attr} attribute according to the WAI-ARIA specification.'
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks @dyc3 — good catch. Added the actionable guidance note to all diagnostic paths:
All 3 pillars now covered: what the error is, why it's wrong, and what to do about it. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs (1)
72-77: Comment drift: implementation skips more than Vue directives.Lines 72-73 read Vue-specific, but Lines 74-77 skip every non-
HtmlAttributevariant. Worth tightening the comment so future readers do not assume Vue is special-cased here (apart from being one example).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs` around lines 72 - 77, The comment above the match that extracts html_attr is misleadingly Vue-specific; update it to state that we only process plain HTML attributes with static values and that all non-HtmlAttribute variants (e.g., Vue directives and any other variants of AnyHtmlAttribute) are skipped. Mention the relevant symbols AnyHtmlAttribute and html_attr (the match that returns None for non-HtmlAttribute cases) so readers know this applies to every non-HtmlAttribute branch, not just Vue.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs`:
- Around line 80-83: The code currently lowercases every attribute name before
checking AriaAttribute::from_str, causing framework-specific props in
.vue/.svelte/.astro files to be misclassified; change the logic to inspect the
source file type and only perform case-folding for plain HTML files: keep the
original extracted name (from extract_html_attribute_name) for template files
(.vue, .svelte, .astro) and use name.to_ascii_lowercase_cow() only when the
current file is an .html file, then pass the appropriate string into
AriaAttribute::from_str so case-sensitive matching is preserved for template
files while .html remains case-insensitive.
---
Nitpick comments:
In `@crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs`:
- Around line 72-77: The comment above the match that extracts html_attr is
misleadingly Vue-specific; update it to state that we only process plain HTML
attributes with static values and that all non-HtmlAttribute variants (e.g., Vue
directives and any other variants of AnyHtmlAttribute) are skipped. Mention the
relevant symbols AnyHtmlAttribute and html_attr (the match that returns None for
non-HtmlAttribute cases) so readers know this applies to every non-HtmlAttribute
branch, not just Vue.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 32065de1-fb54-4147-b0e4-79564c8c6c39
⛔ Files ignored due to path filters (4)
crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/astro/invalid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/invalid.html.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/svelte/invalid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/vue/invalid.vue.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (1)
crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs
dyc3
left a comment
There was a problem hiding this comment.
Oof sorry i missed these on my first pass.
And I would appreciate it if you didn't have the AI write responses on your behalf.
- State: String -> TokenText (zero-copy from CST) - Value check: use &str reference instead of .to_string() - Case-folding: only lowercase for .html files, preserve case in Vue/Svelte/Astro Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs (1)
148-152: Minor wording inconsistency (optional).For
Token, the message uses singular "value ... is one of" whileBoolean/Tristateuse plural "values ... are". Both are grammatically correct, but harmonising would improve consistency.🔧 Optional harmonisation
AriaValueType::Token(tokens) => diagnostic.footer_list( markup! { - "The only supported value for the "<Emphasis>{attribute_name}</Emphasis>" property is one of the following:" + "The only supported values for the "<Emphasis>{attribute_name}</Emphasis>" property are:" }, tokens, ),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs` around lines 148 - 152, The footer message for AriaValueType::Token uses singular phrasing ("The only supported value for the {attribute_name} property is one of...") while Boolean/Tristate use plural; update the string in the AriaValueType::Token diagnostic.footer_list invocation to plural phrasing to match (e.g., "The only supported values for the {attribute_name} property are one of the following:") so wording is consistent with Boolean and Tristate messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs`:
- Around line 148-152: The footer message for AriaValueType::Token uses singular
phrasing ("The only supported value for the {attribute_name} property is one
of...") while Boolean/Tristate use plural; update the string in the
AriaValueType::Token diagnostic.footer_list invocation to plural phrasing to
match (e.g., "The only supported values for the {attribute_name} property are
one of the following:") so wording is consistent with Boolean and Tristate
messages.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b68ec02a-0f98-401b-aa52-0a3775ff6caf
⛔ Files ignored due to path filters (1)
crates/biome_html_analyze/tests/specs/a11y/useValidAriaValues/invalid.html.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (1)
crates/biome_html_analyze/src/lint/a11y/use_valid_aria_values.rs
Summary
Ports the
useValidAriaValueslint rule from JSX to HTML, as part of the umbrella issue #8155.What the rule does
Validates that
aria-*attribute values match the expected types defined by the WAI-ARIA specification:true/false(e.g.,aria-hidden)true/false/mixed(e.g.,aria-checked)aria-level)aria-valuemax)aria-orientation:horizontal/vertical)aria-labelledby)Behavior
.htmlfiles, attribute names are matched case-insensitively (e.g.,ARIA-HIDDEN="true"is valid):aria-checked="expr",v-bind:aria-checked="expr") are skipped — the value is a runtime expression that can't be statically validatedTest plan
valid.html/invalid.html: Boolean, Tristate, Token, Integer, Number, IdReferenceList, case-insensitive attribute namesvue/valid.vue/vue/invalid.vue: Vue framework coverage, dynamic binding skip verificationAll 4 tests pass locally, clippy clean (zero warnings).
Closes part of #8155.
AI Disclosure
This PR was developed with assistance from GitHub Copilot CLI (Claude). The implementation and test cases were reviewed and verified by the author.