From 89dd749a652060a9fb6fba5decb50dad86cef9df Mon Sep 17 00:00:00 2001 From: John Costa Date: Fri, 6 Mar 2026 07:35:45 -0800 Subject: [PATCH 1/3] fix(biome_html_analyze): recognize Astro Image component in useAnchorContent Treat the Astro `` component the same as `` when checking for accessible content inside anchor elements. An `...` inside `` no longer triggers a false positive. Closes #9210 --- .changeset/fix-use-anchor-content-image.md | 5 ++ .../src/lint/a11y/use_anchor_content.rs | 4 +- .../a11y/useAnchorContent/astro/invalid.astro | 6 ++ .../useAnchorContent/astro/invalid.astro.snap | 81 +++++++++++++++---- .../a11y/useAnchorContent/astro/valid.astro | 1 + .../useAnchorContent/astro/valid.astro.snap | 2 + 6 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 .changeset/fix-use-anchor-content-image.md diff --git a/.changeset/fix-use-anchor-content-image.md b/.changeset/fix-use-anchor-content-image.md new file mode 100644 index 000000000000..3a12baffbda9 --- /dev/null +++ b/.changeset/fix-use-anchor-content-image.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [`useAnchorContent`](https://biomejs.dev/linter/rules/use-anchor-content/) false positive when an Astro `Image` component with an `alt` attribute is used inside an anchor element. diff --git a/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs b/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs index 524a8f58a051..856f1494db43 100644 --- a/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs +++ b/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs @@ -212,7 +212,9 @@ fn has_accessible_content(html_child_list: &HtmlElementList) -> bool { let tag_text = element.name().ok().and_then(|n| n.token_text_trimmed()); match tag_text.as_ref().map(|t| t.as_ref()) { - Some(name) if name.eq_ignore_ascii_case("img") => { + Some(name) + if name.eq_ignore_ascii_case("img") || name == "Image" => + { html_self_closing_element_has_non_empty_attribute(element, "alt") } Some(name) diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro index ef06ca900117..4c4a9fa9ab8c 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro @@ -16,6 +16,12 @@ + + + + + +

diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro.snap index 3a5cf1873e3e..e48117c9cae9 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro.snap @@ -1,5 +1,6 @@ --- source: crates/biome_html_analyze/tests/spec_tests.rs +assertion_line: 83 expression: invalid.astro --- # Input @@ -22,6 +23,12 @@ expression: invalid.astro + + + + + +

@@ -181,7 +188,7 @@ invalid.astro:17:1 lint/a11y/useAnchorContent ━━━━━━━━━━━ > 17 │ │ ^^^^^^^^^^^^^^^^^^^^^ 18 │ - 19 │ + 19 │ i All links on a page should have content that is accessible to screen readers. @@ -199,11 +206,55 @@ invalid.astro:20:1 lint/a11y/useAnchorContent ━━━━━━━━━━━ × Provide screen reader accessible content when using a elements. - 19 │ - > 20 │
+ 19 │ + > 20 │ + │ ^^^^^^^^^^^^^^^^ + 21 │ + 22 │ + + i All links on a page should have content that is accessible to screen readers. + + i Accessible content refers to digital content that is designed and structured in a way that makes it easy for people with disabilities to access, understand, and interact with using assistive technologies. + + i Follow these links for more information, + WCAG 2.4.4 + WCAG 4.1.2 + + +``` + +``` +invalid.astro:23:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Provide screen reader accessible content when using a elements. + + 22 │ + > 23 │ + │ ^^^^^^^^^^^^^^^^^^^^^^^ + 24 │ + 25 │ + + i All links on a page should have content that is accessible to screen readers. + + i Accessible content refers to digital content that is designed and structured in a way that makes it easy for people with disabilities to access, understand, and interact with using assistive technologies. + + i Follow these links for more information, + WCAG 2.4.4 + WCAG 4.1.2 + + +``` + +``` +invalid.astro:26:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Provide screen reader accessible content when using a elements. + + 25 │ + > 26 │
│ ^^^^^^^^^^^^^ - 21 │
- 22 │ + 27 │
+ 28 │ i All links on a page should have content that is accessible to screen readers. @@ -217,16 +268,16 @@ invalid.astro:20:1 lint/a11y/useAnchorContent ━━━━━━━━━━━ ``` ``` -invalid.astro:21:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.astro:27:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ × Provide screen reader accessible content when using a elements. - 19 │ - 20 │
- > 21 │
+ 25 │ + 26 │
+ > 27 │
│ ^^^^^^^^^^^^^ - 22 │ - 23 │ + 28 │ + 29 │ i All links on a page should have content that is accessible to screen readers. @@ -240,14 +291,14 @@ invalid.astro:21:1 lint/a11y/useAnchorContent ━━━━━━━━━━━ ``` ``` -invalid.astro:24:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.astro:30:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ × Provide screen reader accessible content when using a elements. - 23 │ - > 24 │ + 29 │ + > 30 │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 25 │ + 31 │ i All links on a page should have content that is accessible to screen readers. diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro index 3b35fb09bc71..4a805afa0664 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro @@ -15,6 +15,7 @@ content content description +description Home diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro.snap index f31816c90732..ca412d20f6a9 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro.snap @@ -1,5 +1,6 @@ --- source: crates/biome_html_analyze/tests/spec_tests.rs +assertion_line: 83 expression: valid.astro --- # Input @@ -21,6 +22,7 @@ expression: valid.astro content content description +description Home From 110d1436f326ce1242555f1291bf9bb82f0b711b Mon Sep 17 00:00:00 2001 From: John Costa Date: Fri, 6 Mar 2026 11:59:38 -0800 Subject: [PATCH 2/3] fix: scope Image component to Astro files and fix changeset format - Only recognize as an image element in Astro files, not Vue/Svelte - Pass is_astro flag through has_accessible_content() recursive calls - Reformat changeset to reference issue #9210 - Add Vue and Svelte test cases proving Image is not recognized outside Astro --- .changeset/fix-use-anchor-content-image.md | 2 +- .../src/lint/a11y/use_anchor_content.rs | 10 ++++--- .../useAnchorContent/svelte/invalid.svelte | 3 ++ .../svelte/invalid.svelte.snap | 25 ++++++++++++++++ .../a11y/useAnchorContent/vue/invalid.vue | 3 ++ .../useAnchorContent/vue/invalid.vue.snap | 29 +++++++++++++++++-- 6 files changed, 65 insertions(+), 7 deletions(-) diff --git a/.changeset/fix-use-anchor-content-image.md b/.changeset/fix-use-anchor-content-image.md index 3a12baffbda9..970a40daa00c 100644 --- a/.changeset/fix-use-anchor-content-image.md +++ b/.changeset/fix-use-anchor-content-image.md @@ -2,4 +2,4 @@ "@biomejs/biome": patch --- -Fixed [`useAnchorContent`](https://biomejs.dev/linter/rules/use-anchor-content/) false positive when an Astro `Image` component with an `alt` attribute is used inside an anchor element. +Fixed [#9210](https://github.com/biomejs/biome/issues/9210): [`useAnchorContent`](https://biomejs.dev/linter/rules/use-anchor-content/) no longer reports an accessibility error for Astro `Image` components inside links when they provide non-empty `alt` text. diff --git a/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs b/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs index 856f1494db43..5c3e8df4011d 100644 --- a/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs +++ b/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs @@ -143,7 +143,8 @@ impl Rule for UseAnchorContent { } // Check if the anchor has accessible content - if has_accessible_content(&html_element.children()) { + let is_astro = source_type.is_astro(); + if has_accessible_content(&html_element.children(), is_astro) { return None; } @@ -190,14 +191,14 @@ impl Rule for UseAnchorContent { } /// Checks if `HtmlElementList` contains accessible content (non-empty text or visible elements). -fn has_accessible_content(html_child_list: &HtmlElementList) -> bool { +fn has_accessible_content(html_child_list: &HtmlElementList, is_astro: bool) -> bool { html_child_list.into_iter().any(|child| match &child { AnyHtmlElement::AnyHtmlContent(content) => is_accessible_text_content(content), AnyHtmlElement::HtmlElement(element) => { if html_element_has_truthy_aria_hidden(element) { false } else { - has_accessible_content(&element.children()) + has_accessible_content(&element.children(), is_astro) } } AnyHtmlElement::HtmlSelfClosingElement(element) => { @@ -213,7 +214,8 @@ fn has_accessible_content(html_child_list: &HtmlElementList) -> bool { match tag_text.as_ref().map(|t| t.as_ref()) { Some(name) - if name.eq_ignore_ascii_case("img") || name == "Image" => + if name.eq_ignore_ascii_case("img") + || (is_astro && name == "Image") => { html_self_closing_element_has_non_empty_attribute(element, "alt") } diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte index e054575d27d9..b3d390a722c4 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte @@ -18,3 +18,6 @@ + + +description diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap index d97c337b854d..a3c80b1e435e 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap @@ -25,6 +25,9 @@ expression: invalid.svelte + +description + ``` # Diagnostics @@ -244,6 +247,28 @@ invalid.svelte:20:1 lint/a11y/useAnchorContent ━━━━━━━━━━━ > 20 │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21 │ + 22 │ + + i All links on a page should have content that is accessible to screen readers. + + i Accessible content refers to digital content that is designed and structured in a way that makes it easy for people with disabilities to access, understand, and interact with using assistive technologies. + + i Follow these links for more information, + WCAG 2.4.4 + WCAG 4.1.2 + + +``` + +``` +invalid.svelte:23:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Provide screen reader accessible content when using a elements. + + 22 │ + > 23 │ description + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 24 │ i All links on a page should have content that is accessible to screen readers. diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue index 4a3330ff183b..3a9145b8bc80 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue @@ -19,4 +19,7 @@ + + + description diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap index 459c31674613..41963820b4b9 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap @@ -25,6 +25,9 @@ expression: invalid.vue + + + description ``` @@ -246,8 +249,30 @@ invalid.vue:21:3 lint/a11y/useAnchorContent ━━━━━━━━━━━━ 20 │ > 21 │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 22 │ - 23 │ + 22 │ + 23 │ + + i All links on a page should have content that is accessible to screen readers. + + i Accessible content refers to digital content that is designed and structured in a way that makes it easy for people with disabilities to access, understand, and interact with using assistive technologies. + + i Follow these links for more information, + WCAG 2.4.4 + WCAG 4.1.2 + + +``` + +``` +invalid.vue:24:3 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Provide screen reader accessible content when using a elements. + + 23 │ + > 24 │ description + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 25 │ + 26 │ i All links on a page should have content that is accessible to screen readers. From 0e3ac96a664e6982799d5ffffb017fb2e19a8372 Mon Sep 17 00:00:00 2001 From: John Costa Date: Sat, 7 Mar 2026 12:47:45 -0800 Subject: [PATCH 3/3] fix: treat PascalCase components as accessible in non-Astro files Custom components like or may render accessible content, so they should not trigger useAnchorContent in Svelte/Vue. The Astro-specific + alt check is preserved since Image is a known built-in that maps to . --- .../src/lint/a11y/use_anchor_content.rs | 2 ++ .../useAnchorContent/svelte/invalid.svelte | 3 -- .../svelte/invalid.svelte.snap | 25 ---------------- .../a11y/useAnchorContent/svelte/valid.svelte | 4 +++ .../useAnchorContent/svelte/valid.svelte.snap | 4 +++ .../a11y/useAnchorContent/vue/invalid.vue | 3 -- .../useAnchorContent/vue/invalid.vue.snap | 29 ++----------------- .../specs/a11y/useAnchorContent/vue/valid.vue | 4 +++ .../a11y/useAnchorContent/vue/valid.vue.snap | 4 +++ 9 files changed, 20 insertions(+), 58 deletions(-) diff --git a/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs b/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs index 5c3e8df4011d..1f8d9cc3f27b 100644 --- a/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs +++ b/crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs @@ -239,6 +239,8 @@ fn has_accessible_content(html_child_list: &HtmlElementList, is_astro: bool) -> }); !is_hidden } + // Custom components (PascalCase) may render accessible content + Some(name) if name.starts_with(|c: char| c.is_uppercase()) => true, _ => false, } } diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte index b3d390a722c4..e054575d27d9 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte @@ -18,6 +18,3 @@ - - -description diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap index a3c80b1e435e..d97c337b854d 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/invalid.svelte.snap @@ -25,9 +25,6 @@ expression: invalid.svelte - -description - ``` # Diagnostics @@ -247,28 +244,6 @@ invalid.svelte:20:1 lint/a11y/useAnchorContent ━━━━━━━━━━━ > 20 │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21 │ - 22 │ - - i All links on a page should have content that is accessible to screen readers. - - i Accessible content refers to digital content that is designed and structured in a way that makes it easy for people with disabilities to access, understand, and interact with using assistive technologies. - - i Follow these links for more information, - WCAG 2.4.4 - WCAG 4.1.2 - - -``` - -``` -invalid.svelte:23:1 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Provide screen reader accessible content when using a elements. - - 22 │ - > 23 │ description - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 24 │ i All links on a page should have content that is accessible to screen readers. diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte index 001fb72ddd66..e8fb306d85f5 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte @@ -16,3 +16,7 @@ + + +description + diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte.snap index 883b33c5036e..679d7053efa0 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte.snap @@ -23,4 +23,8 @@ expression: valid.svelte + +description + + ``` diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue index 3a9145b8bc80..4a3330ff183b 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue @@ -19,7 +19,4 @@ - - - description diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap index 41963820b4b9..459c31674613 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/invalid.vue.snap @@ -25,9 +25,6 @@ expression: invalid.vue - - - description ``` @@ -249,30 +246,8 @@ invalid.vue:21:3 lint/a11y/useAnchorContent ━━━━━━━━━━━━ 20 │ > 21 │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 22 │ - 23 │ - - i All links on a page should have content that is accessible to screen readers. - - i Accessible content refers to digital content that is designed and structured in a way that makes it easy for people with disabilities to access, understand, and interact with using assistive technologies. - - i Follow these links for more information, - WCAG 2.4.4 - WCAG 4.1.2 - - -``` - -``` -invalid.vue:24:3 lint/a11y/useAnchorContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Provide screen reader accessible content when using a elements. - - 23 │ - > 24 │ description - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 25 │ - 26 │ + 22 │ + 23 │ i All links on a page should have content that is accessible to screen readers. diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue index 49d641203266..03630f7be33f 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue @@ -16,4 +16,8 @@ + + + description + diff --git a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue.snap b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue.snap index be8f531c5fe2..5f1378d9c59d 100644 --- a/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue.snap +++ b/crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue.snap @@ -22,6 +22,10 @@ expression: valid.vue + + + description + ```