diff --git a/.changeset/add-use-media-caption-html.md b/.changeset/add-use-media-caption-html.md new file mode 100644 index 000000000000..c827d2e9ddd6 --- /dev/null +++ b/.changeset/add-use-media-caption-html.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": minor +--- + +Added the rule [`useMediaCaption`](https://biomejs.dev/linter/rules/use-media-caption/) to the HTML language. Enforces that `audio` and `video` elements have a `track` element with `kind="captions"` for accessibility. Muted videos are allowed without captions. diff --git a/crates/biome_html_analyze/src/lint/a11y.rs b/crates/biome_html_analyze/src/lint/a11y.rs index 6a1e3562957f..8a7424b25536 100644 --- a/crates/biome_html_analyze/src/lint/a11y.rs +++ b/crates/biome_html_analyze/src/lint/a11y.rs @@ -15,6 +15,7 @@ pub mod use_aria_props_for_role; pub mod use_button_type; pub mod use_html_lang; pub mod use_iframe_title; +pub mod use_media_caption; pub mod use_valid_aria_role; pub mod use_valid_lang; -declare_lint_group! { pub A11y { name : "a11y" , rules : [self :: no_access_key :: NoAccessKey , self :: no_autofocus :: NoAutofocus , self :: no_distracting_elements :: NoDistractingElements , self :: no_header_scope :: NoHeaderScope , self :: no_positive_tabindex :: NoPositiveTabindex , self :: no_redundant_alt :: NoRedundantAlt , self :: no_svg_without_title :: NoSvgWithoutTitle , self :: use_alt_text :: UseAltText , self :: use_aria_props_for_role :: UseAriaPropsForRole , self :: use_button_type :: UseButtonType , self :: use_html_lang :: UseHtmlLang , self :: use_iframe_title :: UseIframeTitle , self :: use_valid_aria_role :: UseValidAriaRole , self :: use_valid_lang :: UseValidLang ,] } } +declare_lint_group! { pub A11y { name : "a11y" , rules : [self :: no_access_key :: NoAccessKey , self :: no_autofocus :: NoAutofocus , self :: no_distracting_elements :: NoDistractingElements , self :: no_header_scope :: NoHeaderScope , self :: no_positive_tabindex :: NoPositiveTabindex , self :: no_redundant_alt :: NoRedundantAlt , self :: no_svg_without_title :: NoSvgWithoutTitle , self :: use_alt_text :: UseAltText , self :: use_aria_props_for_role :: UseAriaPropsForRole , self :: use_button_type :: UseButtonType , self :: use_html_lang :: UseHtmlLang , self :: use_iframe_title :: UseIframeTitle , self :: use_media_caption :: UseMediaCaption , self :: use_valid_aria_role :: UseValidAriaRole , self :: use_valid_lang :: UseValidLang ,] } } diff --git a/crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs b/crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs new file mode 100644 index 000000000000..d103983bb20b --- /dev/null +++ b/crates/biome_html_analyze/src/lint/a11y/use_media_caption.rs @@ -0,0 +1,160 @@ +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, HtmlElementList, HtmlFileSource}; +use biome_rowan::AstNode; + +declare_lint_rule! { + /// Enforces that `audio` and `video` elements must have a `track` for captions. + /// + /// Captions support users with hearing-impairments. They should be a transcription + /// or translation of the dialogue, sound effects, musical cues, and other relevant + /// audio information. + /// + /// :::note + /// In `.html` files, this rule matches element names case-insensitively (e.g., `