Skip to content

feat(biome_html_analyze): add useMediaCaption rule for HTML#8742

Merged
ematipico merged 11 commits intobiomejs:nextfrom
rahuld109:use-media-caption-html
Jan 15, 2026
Merged

feat(biome_html_analyze): add useMediaCaption rule for HTML#8742
ematipico merged 11 commits intobiomejs:nextfrom
rahuld109:use-media-caption-html

Conversation

@rahuld109
Copy link
Contributor

@rahuld109 rahuld109 commented Jan 11, 2026

Note

AI Assistance Disclosure: The Rust implementation in this PR was developed with Claude Code. While I have experience with web accessibility and a11y standards, I am still learning Rust.

Summary

Ports the useMediaCaption a11y rule to HTML, as part of #8155.

The rule enforces that <audio> and <video> elements have a <track kind="captions"> child for accessibility. Muted videos are allowed without captions (muted audio still requires captions).

Invalid

<video src="video.mp4"></video>
<audio src="audio.mp3"></audio>
<video>
    <track kind="subtitles" src="subtitles.vtt" />
</video>
<audio muted src="audio.mp3"></audio>

Valid

<video src="video.mp4">
    <track kind="captions" src="captions.vtt" />
</video>
<video muted src="video.mp4"></video>

Test Plan

  • Added test cases for invalid HTML (missing track, wrong kind, missing/empty kind attribute, muted audio)
  • Added test cases for valid HTML (with captions track, muted videos, case-insensitive kind check)
  • All HTML analyzer tests pass

Docs

Documentation is included in the rule's inline rustdoc. The rule is a port of the existing JSX rule, so the website docs already exist.

@changeset-bot
Copy link

changeset-bot bot commented Jan 11, 2026

🦋 Changeset detected

Latest commit: 0f23f78

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@biomejs/biome Minor
@biomejs/cli-win32-x64 Minor
@biomejs/cli-win32-arm64 Minor
@biomejs/cli-darwin-x64 Minor
@biomejs/cli-darwin-arm64 Minor
@biomejs/cli-linux-x64 Minor
@biomejs/cli-linux-arm64 Minor
@biomejs/cli-linux-x64-musl Minor
@biomejs/cli-linux-arm64-musl Minor
@biomejs/wasm-web Minor
@biomejs/wasm-bundler Minor
@biomejs/wasm-nodejs Minor
@biomejs/backend-jsonrpc Patch
@biomejs/js-api Major

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

@github-actions github-actions bot added A-Linter Area: linter L-HTML Language: HTML and super languages labels Jan 11, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 12, 2026

Walkthrough

Adds a new HTML accessibility lint rule UseMediaCaption that requires audio and video elements to include a child track element with kind="captions" (muted videos are exempt). Implements the rule in a new use_media_caption module, registers UseMediaCaption in the A11y lint group, and adds test fixtures (valid/invalid) for HTML, Astro, Svelte and Vue to exercise diagnostics and exemptions.

Possibly related PRs

Suggested reviewers

  • ematipico
  • dyc3
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarises the main change: adding a new useMediaCaption lint rule for HTML analysis.
Description check ✅ Passed The description clearly relates to the changeset, explaining the rule's purpose, providing examples, and outlining test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 520312a and 0f23f78.

📒 Files selected for processing (1)
  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use the dbg!() macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests

Files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧠 Learnings (19)
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule names should use the `use` prefix when the rule's sole intention is to mandate a single concept

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Deprecated rules must include a `deprecated` field in the `declare_lint_rule!` macro with an explanation of what rule to use instead

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `action` function and add `fix_kind` metadata to the rule macro if the rule provides code actions

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `rule_category!()` macro to refer to the diagnostic category instead of dynamically parsing its string name

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-12-22T09:26:56.943Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8537
File: crates/biome_js_analyze/src/lint/nursery/no_leaked_render.rs:167-210
Timestamp: 2025-12-22T09:26:56.943Z
Learning: When defining lint rules (declare_lint_rule!), only specify fix_kind if the rule implements an action(...) function. Rules that only emit diagnostics without a code fix should omit fix_kind. This applies to all Rust lint rule definitions under crates/.../src/lint (e.g., crates/biome_js_analyze/src/lint/...).

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `Markup!` macro for diagnostic messages and code action descriptions to ensure proper formatting

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_lint_rule!` macro with a `version` field set to `next` for new rules

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : The first paragraph of rule documentation must be written in a single line to ensure proper rendering in the rules overview table

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Invalid code snippets in rule documentation must emit exactly one diagnostic

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Code blocks in rule documentation must specify a language identifier and be tagged with `expect_diagnostic` for invalid examples or remain untagged for valid examples

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Biome linter rules must be designed to work across languages, requiring careful naming to indicate intended scope

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For tokens that are not mandatory, use helper functions instead of hardcoding

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/language.rs : Implement `TestFormatLanguage` trait in `tests/language.rs` for the formatter's test language

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : All grammar nodes must start with the prefix of the language, e.g., `HtmlSimpleAttribute`

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Avoid string allocations by using `&str` or `TokenText` instead of `to_string()`

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : When porting rules from other linters, use `sources` metadata with `RuleSource::Eslint().same()` for identical behavior or `.inspired()` for different behavior

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `Semantic<T>` query type to access semantic information about bindings, references, and scope within a rule

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule documentation must include an `## Examples` section followed by `### Invalid` and `### Valid` subsections, with Invalid appearing first

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement custom `Queryable` and `Visitor` types for rules that require deep inspection of child nodes to avoid inefficient traversals

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🔇 Additional comments (5)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (5)

1-7: LGTM!

Imports are minimal and appropriate for the rule implementation.


9-68: LGTM!

Rule declaration follows conventions nicely: single-line first paragraph, version: "next", proper sources metadata, and examples in the correct order with appropriate tags. The note about case-sensitivity behaviour is a helpful addition for users.


116-131: LGTM!

Diagnostic uses rule_category!() and markup! correctly. The message is clear and the note provides helpful context about why captions matter.


133-160: LGTM!

Helper function correctly handles case-sensitivity for element names based on source type, and the kind attribute value comparison is appropriately case-insensitive. The use of find_map(...).is_some() is clean.


97-100: No action needed—attribute lookup is already case-insensitive.

find_attribute_by_name uses eq_ignore_ascii_case internally, so <video muted>, <VIDEO MUTED>, and other case variants all match correctly. The code is already handling this properly per the HTML specification.

Likely an incorrect or invalid review comment.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs:
- Around line 78-81: The current muted-exemption checks
node.find_attribute_by_name("muted") for any media element; change it to only
exempt when the element is a <video> with the muted attribute. In the
use_media_caption lint (use_media_caption.rs), update the conditional to first
verify the node tag/name is "video" (e.g., node.tag_name(), node.name(), or
however the element name is obtained) and only then check
node.find_attribute_by_name("muted").is_some() to return None; do not
short-circuit for <audio> or other elements.
🧹 Nitpick comments (2)
crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/invalid.html (1)

10-13: Consider adding edge case tests.

The test covers kind="subtitles", but you might also want to test:

  • <track src="captions.vtt" /> (missing kind attribute)
  • <track kind="" src="captions.vtt" /> (empty kind)

These would help ensure the rule correctly flags all non-caption track scenarios.

crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (1)

1-7: Move import to the top of the file.

The use biome_html_syntax::HtmlElementList; import at line 110 should be grouped with the other imports at the top of the file for consistency.

♻️ Suggested fix
 use biome_analyze::{
     Ast, Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule,
 };
 use biome_console::markup;
 use biome_diagnostics::Severity;
-use biome_html_syntax::AnyHtmlElement;
+use biome_html_syntax::{AnyHtmlElement, HtmlElementList};
 use biome_rowan::AstNode;

Then remove line 110.

Also applies to: 110-110

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe2c642 and b8af3bb.

⛔ Files ignored due to path filters (2)
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (5)
  • .changeset/add-use-media-caption-html.md
  • crates/biome_html_analyze/src/lint/a11y.rs
  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/invalid.html
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use the dbg!() macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests

Files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
🧠 Learnings (18)
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/* : Create test files with `invalid` and `valid` prefixes to represent code that should and should not trigger the rule

Applied to files:

  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/invalid.html
📚 Learning: 2025-12-04T13:29:49.287Z
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.

Applied to files:

  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule names should use the `use` prefix when the rule's sole intention is to mandate a single concept

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `Markup!` macro for diagnostic messages and code action descriptions to ensure proper formatting

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Deprecated rules must include a `deprecated` field in the `declare_lint_rule!` macro with an explanation of what rule to use instead

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `rule_category!()` macro to refer to the diagnostic category instead of dynamically parsing its string name

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `action` function and add `fix_kind` metadata to the rule macro if the rule provides code actions

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_lint_rule!` macro with a `version` field set to `next` for new rules

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2025-12-22T09:26:56.943Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8537
File: crates/biome_js_analyze/src/lint/nursery/no_leaked_render.rs:167-210
Timestamp: 2025-12-22T09:26:56.943Z
Learning: When defining lint rules (declare_lint_rule!), only specify fix_kind if the rule implements an action(...) function. Rules that only emit diagnostics without a code fix should omit fix_kind. This applies to all Rust lint rule definitions under crates/.../src/lint (e.g., crates/biome_js_analyze/src/lint/...).

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `diagnostic` function to provide error messages explaining what the error is, why it is triggered, and what the user should do

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Code blocks in rule documentation must specify a language identifier and be tagged with `expect_diagnostic` for invalid examples or remain untagged for valid examples

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Invalid code snippets in rule documentation must emit exactly one diagnostic

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : When porting rules from other linters, use `sources` metadata with `RuleSource::Eslint().same()` for identical behavior or `.inspired()` for different behavior

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `Semantic<T>` query type to access semantic information about bindings, references, and scope within a rule

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule documentation must include an `## Examples` section followed by `### Invalid` and `### Valid` subsections, with Invalid appearing first

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : New rules must be placed inside the `nursery` group before promotion to other groups

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Mark rules with `issue_number` in the `declare_lint_rule!` macro if they are work-in-progress to indicate missing features

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : The first paragraph of rule documentation must be written in a single line to ensure proper rendering in the rules overview table

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y.rs
🧬 Code graph analysis (1)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (3)
crates/biome_service/src/workspace.rs (1)
  • markup (1223-1225)
packages/@biomejs/plugin-api/index.d.ts (1)
  • Severity (1-1)
crates/biome_html_syntax/src/attr_ext.rs (1)
  • string_value (9-19)
🔇 Additional comments (5)
.changeset/add-use-media-caption-html.md (1)

1-5: LGTM!

Changeset is well-written with a clear, concise description of the new rule.

crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html (1)

8-12: Missing test for muted audio.

The PR description mentions "Muted videos are allowed without captions", but the rule implementation also exempts muted <audio> elements. Consider adding a test to clarify the intended behaviour:

<!-- muted audio - if intentionally exempt -->
<audio muted src="audio.mp3"></audio>

If muted audio should not be exempt, the rule implementation needs adjustment.

crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (2)

93-107: LGTM!

Diagnostic implementation is clean, follows conventions, and provides helpful context for developers.


112-139: LGTM!

The helper function is well-documented and handles edge cases properly. The case-insensitive check for "captions" is a nice touch.

crates/biome_html_analyze/src/lint/a11y.rs (1)

18-21: No issue. This is a ported rule from the JS analyser (where it already exists in a11y), so placing it directly in the a11y group for HTML is the correct approach. The sources metadata correctly references EslintJsxA11y with .same() for identical behaviour, and the severity is set to Error as required for a11y rules.

@rahuld109 rahuld109 force-pushed the use-media-caption-html branch from 400af9b to ade0283 Compare January 12, 2026 00:05
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (1)

84-87: Clarify the intent of the opening_element().is_ok() guard.

If opening_element() returns Err, this condition evaluates to false, causing a diagnostic to be emitted even though we couldn't inspect children. This might produce false positives on malformed HTML. If the intent is to skip analysis when the element can't be fully parsed, consider returning None explicitly:

♻️ Suggested alternative
-        if html_element.opening_element().is_ok() && has_caption_track(&html_element.children()) {
+        if html_element.opening_element().is_err() {
+            return None;
+        }
+        if has_caption_track(&html_element.children()) {
             return None;
         }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbd6019 and ade0283.

⛔ Files ignored due to path filters (2)
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (3)
  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/invalid.html
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/valid.html
  • crates/biome_html_analyze/tests/specs/a11y/useMediaCaption/invalid.html
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use the dbg!() macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests

Files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧠 Learnings (13)
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule names should use the `use` prefix when the rule's sole intention is to mandate a single concept

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `Markup!` macro for diagnostic messages and code action descriptions to ensure proper formatting

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `rule_category!()` macro to refer to the diagnostic category instead of dynamically parsing its string name

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `action` function and add `fix_kind` metadata to the rule macro if the rule provides code actions

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Deprecated rules must include a `deprecated` field in the `declare_lint_rule!` macro with an explanation of what rule to use instead

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-12-22T09:26:56.943Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8537
File: crates/biome_js_analyze/src/lint/nursery/no_leaked_render.rs:167-210
Timestamp: 2025-12-22T09:26:56.943Z
Learning: When defining lint rules (declare_lint_rule!), only specify fix_kind if the rule implements an action(...) function. Rules that only emit diagnostics without a code fix should omit fix_kind. This applies to all Rust lint rule definitions under crates/.../src/lint (e.g., crates/biome_js_analyze/src/lint/...).

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_lint_rule!` macro with a `version` field set to `next` for new rules

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Code blocks in rule documentation must specify a language identifier and be tagged with `expect_diagnostic` for invalid examples or remain untagged for valid examples

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `diagnostic` function to provide error messages explaining what the error is, why it is triggered, and what the user should do

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Invalid code snippets in rule documentation must emit exactly one diagnostic

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : When porting rules from other linters, use `sources` metadata with `RuleSource::Eslint().same()` for identical behavior or `.inspired()` for different behavior

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `Semantic<T>` query type to access semantic information about bindings, references, and scope within a rule

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule documentation must include an `## Examples` section followed by `### Invalid` and `### Valid` subsections, with Invalid appearing first

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🔇 Additional comments (2)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (2)

9-61: Well-structured rule declaration.

Documentation follows the required format with Invalid before Valid, proper expect_diagnostic tags, and relevant WCAG references. Metadata is appropriate: version: "next" for new rules, no fix_kind since there's no code action. Based on learnings, this follows biome conventions correctly.


110-137: Solid helper implementation.

The logic correctly handles edge cases: missing kind attribute, empty values, and case variations. The case-insensitive comparison on line 135 is particularly good for robustness.

Minor nit: into_iter() on a reference works, but .iter() is slightly more idiomatic when you're not consuming the collection.

@dyc3 dyc3 mentioned this pull request Jan 12, 2026
32 tasks
@codspeed-hq
Copy link

codspeed-hq bot commented Jan 12, 2026

CodSpeed Performance Report

Merging this PR will not alter performance

Comparing rahuld109:use-media-caption-html (0f23f78) with next (fe2c642)1

Summary

✅ 3 untouched benchmarks
🆕 1 new benchmark
⏩ 152 skipped benchmarks2

Performance Changes

Benchmark BASE HEAD Efficiency
🆕 html_analyzer[index_1033418810622582172.html] N/A 373.4 µs N/A

Footnotes

  1. No successful run was found on next (c594a36) during the generation of this report, so fe2c642 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 152 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I added some comments that must be addressed. Also, we must add more tests, notably some Vue/svelte/Astro files (one of them is enough), so we can test that components don't trigger the rule

- Change changeset to minor
- Use HtmlFileSource for case-insensitive tag matching in HTML
- Use filter_map instead of any for cleaner code
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (1)

150-153: Consider simplifying with .any().

The .filter_map(...).next().is_some() pattern works, but could be more idiomatic:

♻️ Suggested simplification
-            if string_value.eq_ignore_ascii_case("captions") {
-                Some(())
-            } else {
-                None
-            }
-        })
-        .next()
-        .is_some()
+            string_value.eq_ignore_ascii_case("captions")
+        })
+        .any(|is_caption| is_caption)

Or even restructure the whole function to use any() directly, similar to the JS version in crates/biome_js_analyze/src/lint/a11y/use_media_caption.rs.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ade0283 and 9571ede.

📒 Files selected for processing (2)
  • .changeset/add-use-media-caption-html.md
  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use the dbg!() macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests

Files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧠 Learnings (20)
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule names should use the `use` prefix when the rule's sole intention is to mandate a single concept

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Deprecated rules must include a `deprecated` field in the `declare_lint_rule!` macro with an explanation of what rule to use instead

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `rule_category!()` macro to refer to the diagnostic category instead of dynamically parsing its string name

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `action` function and add `fix_kind` metadata to the rule macro if the rule provides code actions

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-12-22T09:26:56.943Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8537
File: crates/biome_js_analyze/src/lint/nursery/no_leaked_render.rs:167-210
Timestamp: 2025-12-22T09:26:56.943Z
Learning: When defining lint rules (declare_lint_rule!), only specify fix_kind if the rule implements an action(...) function. Rules that only emit diagnostics without a code fix should omit fix_kind. This applies to all Rust lint rule definitions under crates/.../src/lint (e.g., crates/biome_js_analyze/src/lint/...).

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_lint_rule!` macro with a `version` field set to `next` for new rules

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `Markup!` macro for diagnostic messages and code action descriptions to ensure proper formatting

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Code blocks in rule documentation must specify a language identifier and be tagged with `expect_diagnostic` for invalid examples or remain untagged for valid examples

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Invalid code snippets in rule documentation must emit exactly one diagnostic

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : The first paragraph of rule documentation must be written in a single line to ensure proper rendering in the rules overview table

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Biome linter rules must be designed to work across languages, requiring careful naming to indicate intended scope

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For tokens that are not mandatory, use helper functions instead of hardcoding

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/language.rs : Implement `TestFormatLanguage` trait in `tests/language.rs` for the formatter's test language

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : All grammar nodes must start with the prefix of the language, e.g., `HtmlSimpleAttribute`

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Avoid string allocations by using `&str` or `TokenText` instead of `to_string()`

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : When porting rules from other linters, use `sources` metadata with `RuleSource::Eslint().same()` for identical behavior or `.inspired()` for different behavior

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `Semantic<T>` query type to access semantic information about bindings, references, and scope within a rule

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule documentation must include an `## Examples` section followed by `### Invalid` and `### Valid` subsections, with Invalid appearing first

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-08-05T14:43:29.581Z
Learnt from: dyc3
Repo: biomejs/biome PR: 7081
File: packages/@biomejs/biome/configuration_schema.json:7765-7781
Timestamp: 2025-08-05T14:43:29.581Z
Learning: The file `packages/biomejs/biome/configuration_schema.json` is auto-generated and should not be manually edited or reviewed for schema issues; any changes should be made at the code generation source.

Applied to files:

  • .changeset/add-use-media-caption-html.md
📚 Learning: 2025-09-25T12:32:59.003Z
Learnt from: arendjr
Repo: biomejs/biome PR: 7593
File: crates/biome_service/src/workspace/server.rs:1306-1306
Timestamp: 2025-09-25T12:32:59.003Z
Learning: In the biomejs/biome project, do not flag compilation errors during code review as they are handled by the existing test infrastructure and CI. Focus on other code quality aspects instead.

Applied to files:

  • .changeset/add-use-media-caption-html.md
🧬 Code graph analysis (1)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (2)
crates/biome_analyze/src/rule.rs (3)
  • sources (641-644)
  • same (252-257)
  • recommended (626-629)
crates/biome_js_analyze/src/lint/a11y/use_media_caption.rs (1)
  • Rule (45-121)
🪛 LanguageTool
.changeset/add-use-media-caption-html.md

[style] ~5-~5: This phrase is redundant (‘L’ stands for ‘language’). Use simply “HTML”.
Context: ...dev/linter/rules/use-media-caption/) to the HTML language. Enforces that audio and video elem...

(ACRONYM_TAUTOLOGY)

🔇 Additional comments (3)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (2)

9-61: LGTM!

The rule declaration follows all conventions: use prefix, version: "next", proper documentation structure with Invalid examples before Valid, and correct WCAG accessibility references. The sources metadata with .same() correctly indicates identical behaviour to the ESLint JSX A11y rule.


63-124: LGTM!

Clean implementation that correctly:

  • Handles case-insensitive tag matching for HTML source types
  • Exempts muted videos whilst still requiring captions for muted audio
  • Skips malformed HTML to avoid false positives

The diagnostic message and note are well-crafted and consistent with the JS version.

.changeset/add-use-media-caption-html.md (1)

1-5: LGTM!

The changeset correctly describes the new rule. Minor nit: "HTML language" is technically redundant since HTML already contains "Language", but this is perfectly acceptable for clarity.

@rahuld109 rahuld109 requested a review from ematipico January 12, 2026 19:24
Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rahuld109 I don't see the new tests, as requested in my review. Can you please add them?

@rahuld109
Copy link
Contributor Author

@rahuld109 I don't see the new tests, as requested in my review. Can you please add them?

Apologies for the oversight. I have now added tests for Vue, Svelte, and Astro that mirror the HTML tests with verification that custom components don't trigger the rule.

@rahuld109 rahuld109 requested a review from ematipico January 13, 2026 01:39
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (1)

126-153: Consider consistent case-sensitivity handling for the kind attribute value.

The track element name uses conditional case-sensitivity based on source_type.is_html() (lines 132-136), but the kind="captions" value comparison (line 146) always uses case-insensitive matching.

Per HTML spec, track kind values are indeed ASCII case-insensitive, so this is technically correct for HTML. However, for non-HTML sources (Vue, Svelte, Astro) where you use case-sensitive element matching, you may want to consider applying the same logic to the attribute value for consistency:

let matches_captions = if source_type.is_html() {
    string_value.eq_ignore_ascii_case("captions")
} else {
    string_value.text() == "captions"
};

That said, since JSX/templating languages typically still follow HTML semantics for standard elements, the current behaviour is defensible.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 155d31b and 520312a.

📒 Files selected for processing (1)
  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use the dbg!() macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests

Files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧠 Learnings (18)
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule names should use the `use` prefix when the rule's sole intention is to mandate a single concept

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Deprecated rules must include a `deprecated` field in the `declare_lint_rule!` macro with an explanation of what rule to use instead

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `action` function and add `fix_kind` metadata to the rule macro if the rule provides code actions

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `rule_category!()` macro to refer to the diagnostic category instead of dynamically parsing its string name

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-12-22T09:26:56.943Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8537
File: crates/biome_js_analyze/src/lint/nursery/no_leaked_render.rs:167-210
Timestamp: 2025-12-22T09:26:56.943Z
Learning: When defining lint rules (declare_lint_rule!), only specify fix_kind if the rule implements an action(...) function. Rules that only emit diagnostics without a code fix should omit fix_kind. This applies to all Rust lint rule definitions under crates/.../src/lint (e.g., crates/biome_js_analyze/src/lint/...).

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `Markup!` macro for diagnostic messages and code action descriptions to ensure proper formatting

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_lint_rule!` macro with a `version` field set to `next` for new rules

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : The first paragraph of rule documentation must be written in a single line to ensure proper rendering in the rules overview table

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Invalid code snippets in rule documentation must emit exactly one diagnostic

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Code blocks in rule documentation must specify a language identifier and be tagged with `expect_diagnostic` for invalid examples or remain untagged for valid examples

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Biome linter rules must be designed to work across languages, requiring careful naming to indicate intended scope

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For tokens that are not mandatory, use helper functions instead of hardcoding

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/language.rs : Implement `TestFormatLanguage` trait in `tests/language.rs` for the formatter's test language

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : All grammar nodes must start with the prefix of the language, e.g., `HtmlSimpleAttribute`

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Avoid string allocations by using `&str` or `TokenText` instead of `to_string()`

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : When porting rules from other linters, use `sources` metadata with `RuleSource::Eslint().same()` for identical behavior or `.inspired()` for different behavior

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `Semantic<T>` query type to access semantic information about bindings, references, and scope within a rule

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule documentation must include an `## Examples` section followed by `### Invalid` and `### Valid` subsections, with Invalid appearing first

Applied to files:

  • crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs
🧬 Code graph analysis (1)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (2)
crates/biome_analyze/src/rule.rs (3)
  • sources (641-644)
  • same (252-257)
  • recommended (626-629)
crates/biome_html_syntax/src/attr_ext.rs (1)
  • string_value (9-19)
🔇 Additional comments (2)
crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs (2)

9-61: Well-structured rule declaration.

Documentation follows the required format with single-line first paragraph, proper ### Invalid before ### Valid subsections, and appropriate expect_diagnostic tags. The version: "next" and sources metadata with .same() are correctly applied. Based on learnings, this aligns with best practices for new lint rules.


69-107: Logic looks sound.

The implementation correctly:

  • Uses case-insensitive matching for HTML and case-sensitive for templating languages.
  • Exempts muted videos whilst still requiring captions for muted audio (as per PR objectives).
  • Defensively skips unparseable elements to avoid false positives.

@ematipico ematipico merged commit 6340ce6 into biomejs:next Jan 15, 2026
17 checks passed
@github-actions github-actions bot mentioned this pull request Feb 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Linter Area: linter L-HTML Language: HTML and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants