fix(biome_html_analyze): recognize Astro Image component in useAnchorContent#9369
Conversation
🦋 Changeset detectedLatest commit: 0e3ac96 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 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 |
WalkthroughThis PR fixes a false positive in the Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 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: 2
🤖 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/fix-use-anchor-content-image.md:
- Line 5: Change the changeset line to use the issue-based bug-fix format and
user-facing wording: replace the current sentence about a "false positive" with
a line beginning "Fixed [`#ISSUE_NUMBER`](issue link): ..." that describes the
visible behavior (e.g., "Anchor elements with an Astro Image component that has
an alt attribute are no longer flagged") and include the existing link to
useAnchorContent; update the reference to the Astro Image component and its alt
attribute so the note reads as an end-user fix rather than an internal
diagnostic.
In `@crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs`:
- Around line 215-217: The branch that treats a PascalCase "Image" as exempt
must be limited to Astro files: update has_accessible_content (or its caller) to
accept a source/type flag (e.g., SourceType or is_astro boolean) and change the
match arm Some(name) if name.eq_ignore_ascii_case("img") || name == "Image" to
only allow the "Image" special-case when the source is Astro (e.g., name ==
"Image" && is_astro) so custom components in Vue/Svelte won't be exempt; adjust
all call sites to pass the source info or determine file source earlier and
thread it into has_accessible_content.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: dd565063-7e1b-434f-a656-189f0f8e0c09
⛔ Files ignored due to path filters (2)
crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (4)
.changeset/fix-use-anchor-content-image.mdcrates/biome_html_analyze/src/lint/a11y/use_anchor_content.rscrates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astrocrates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro
ematipico
left a comment
There was a problem hiding this comment.
- restore our PR template
- address the bot suggestions
…Content Treat the Astro `<Image>` component the same as `<img>` when checking for accessible content inside anchor elements. An `<Image alt="...">` inside `<a>` no longer triggers a false positive. Closes biomejs#9210
e4814cc to
89dd749
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (2)
crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs (1)
215-217:⚠️ Potential issue | 🟠 MajorPlease keep the
Imageexemption Astro-only.This now treats any PascalCase
<Image>in non-HTML files as equivalent to<img>, so a custom Vue/Svelte component can slip past the rule if it happens to exposealt. Please thread the source type intohas_accessible_content()and only allow this branch for Astro.🤖 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_anchor_content.rs` around lines 215 - 217, The patch currently treats a PascalCase "Image" tag the same as an HTML <img>, which allows non-Astro frameworks to bypass the rule; update has_accessible_content(...) to accept (or be passed) the source/context/source_type (e.g., an enum or &str) and restrict the special-case branch that checks Some(name) if name.eq_ignore_ascii_case("img") || name == "Image" so that the name == "Image" exemption only applies when source_type == Astro; leave the img check unchanged for all sources and adjust callers of has_accessible_content (and its signature) accordingly so only Astro files get the PascalCase Image exemption..changeset/fix-use-anchor-content-image.md (1)
5-5:⚠️ Potential issue | 🟡 MinorUse the issue-linked bug-fix template here.
Line 5 still starts with the rule link rather than the issue link, and “false positive” reads a bit too implementation-heavy for a changeset. Please switch it to the
Fixed [#9210](...)format and describe the visible user-facing fix.As per coding guidelines, bug fix changesets should start with
'Fixed [#NUMBER](issue link): ...'format and be written for end users.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.changeset/fix-use-anchor-content-image.md at line 5, Update the changeset header to the bug-fix template: replace the current rule-link start on line 5 with "Fixed [`#9210`](issue URL): ..." and reword the message to a user-facing description explaining that the useAnchorContent linter no longer incorrectly flags anchor elements that contain an Astro Image component with an alt attribute (i.e., mention useAnchorContent and "Astro Image with alt" so reviewers can locate the change), ensuring the phrasing is for end users rather than implementation details.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In @.changeset/fix-use-anchor-content-image.md:
- Line 5: Update the changeset header to the bug-fix template: replace the
current rule-link start on line 5 with "Fixed [`#9210`](issue URL): ..." and
reword the message to a user-facing description explaining that the
useAnchorContent linter no longer incorrectly flags anchor elements that contain
an Astro Image component with an alt attribute (i.e., mention useAnchorContent
and "Astro Image with alt" so reviewers can locate the change), ensuring the
phrasing is for end users rather than implementation details.
In `@crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs`:
- Around line 215-217: The patch currently treats a PascalCase "Image" tag the
same as an HTML <img>, which allows non-Astro frameworks to bypass the rule;
update has_accessible_content(...) to accept (or be passed) the
source/context/source_type (e.g., an enum or &str) and restrict the special-case
branch that checks Some(name) if name.eq_ignore_ascii_case("img") || name ==
"Image" so that the name == "Image" exemption only applies when source_type ==
Astro; leave the img check unchanged for all sources and adjust callers of
has_accessible_content (and its signature) accordingly so only Astro files get
the PascalCase Image exemption.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1ab6b6dc-1b90-4271-b9e3-8554c34fc8dd
⛔ Files ignored due to path filters (2)
crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (4)
.changeset/fix-use-anchor-content-image.mdcrates/biome_html_analyze/src/lint/a11y/use_anchor_content.rscrates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astrocrates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/valid.astro
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/astro/invalid.astro
- Only recognize <Image> 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 biomejs#9210 - Add Vue and Svelte test cases proving Image is not recognized outside Astro
Merging this PR will not alter performance
Comparing Footnotes
|
| <a><input type="hidden" /></a> | ||
|
|
||
| <!-- Image component is not recognized outside Astro --> | ||
| <a><Image alt="description" /></a> |
There was a problem hiding this comment.
This should be valid. We can't know if the component will render some accessible content or not, which means we should NOT trigger this
Custom components like <Image> or <CustomIcon> may render accessible content, so they should not trigger useAnchorContent in Svelte/Vue. The Astro-specific <Image> + alt check is preserved since Image is a known built-in that maps to <img>.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/tests/specs/a11y/useAnchorContent/svelte/valid.svelte`:
- Around line 20-22: The test currently treats non-Astro components inside
anchors as accessible (lines with <a><Image alt="description" /></a> and
<a><CustomIcon /></a>), which makes the rule too optimistic for Svelte; update
the spec so only Astro-scoped valid cases are blessed: either replace the
non-Astro components (Image, CustomIcon) with concrete accessible HTML (e.g.,
<img alt="..."> or text) or move these cases to the invalid tests so the rule
correctly flags custom component children in <a> as not automatically
accessible. Ensure you edit the entries referencing Image and CustomIcon in the
Svelte test to reflect this change.
In `@crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue`:
- Around line 20-22: The test includes non-Astro Vue component cases (<Image
alt="description" /> and <CustomIcon />) in the `valid` fixture which
incorrectly asserts that arbitrary component children satisfy the
useAnchorContent rule; remove or relocate these Vue component anchor cases from
this `valid.vue` file (lines showing <a><Image ... /></a> and <a><CustomIcon
/></a>) and instead place them in an appropriate Vue-specific fixture or mark
them as invalid/explicit Astro-only tests so `useAnchorContent` only treats
Astro component behavior in this `valid` suite.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 199a2782-1ff8-49c1-8a9a-c6c48a785b3a
⛔ Files ignored due to path filters (2)
crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (3)
crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rscrates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.sveltecrates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs
crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/svelte/valid.svelte
Show resolved
Hide resolved
| <!-- Custom components may render accessible content --> | ||
| <a><Image alt="description" /></a> | ||
| <a><CustomIcon /></a> |
There was a problem hiding this comment.
Keep the non-Astro fixtures out of valid here.
Line 21 and Line 22 codify that Vue custom components satisfy useAnchorContent, which is broader than the Astro-only fix from #9210. That would lock in false negatives for anchors whose component children render no accessible text.
Suggested adjustment
- <!-- Custom components may render accessible content -->
- <a><Image alt="description" /></a>
- <a><CustomIcon /></a>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue`
around lines 20 - 22, The test includes non-Astro Vue component cases (<Image
alt="description" /> and <CustomIcon />) in the `valid` fixture which
incorrectly asserts that arbitrary component children satisfy the
useAnchorContent rule; remove or relocate these Vue component anchor cases from
this `valid.vue` file (lines showing <a><Image ... /></a> and <a><CustomIcon
/></a>) and instead place them in an appropriate Vue-specific fixture or mark
them as invalid/explicit Astro-only tests so `useAnchorContent` only treats
Astro component behavior in this `valid` suite.
There was a problem hiding this comment.
@coderabbitai that's the whole point of the test. Since we don't know if a possible component renders something, we add a test to make sure it doesn't trigger a false positive. The previous commit mistakenly emitted a diagnostic
There was a problem hiding this comment.
@ematipico, understood — my mistake! Since the linter has no visibility into what a custom component ultimately renders, flagging <a><CustomComponent /></a> as lacking accessible content would indeed be a false positive. Treating PascalCase components as potentially accessible content is the correct conservative approach here.
✏️ Learnings added
Learnt from: ematipico
Repo: biomejs/biome PR: 9369
File: crates/biome_html_analyze/tests/specs/a11y/useAnchorContent/vue/valid.vue:20-22
Timestamp: 2026-03-08T08:18:28.023Z
Learning: In `crates/biome_html_analyze/src/lint/a11y/use_anchor_content.rs` (biomejs/biome), custom components (PascalCase elements) inside `<a>` tags are intentionally treated as potentially accessible content to avoid false positives. The linter cannot statically determine what a custom component renders, so it must not emit a diagnostic for anchors whose only children are custom components. The `valid` fixture files for non-Astro frameworks (e.g., vue/valid.vue, svelte/valid.svelte) correctly include cases like `<a><Image alt="description" /></a>` and `<a><CustomIcon /></a>` as valid to document this behavior.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
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.
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:27:13.161Z
Learning: In crates/biome_analyze/**/*analyze/src/**/*.rs, the `fix_kind` field in `declare_lint_rule!` should only be specified when the rule implements the `action` function. Rules that only emit diagnostics without providing code fixes should not include `fix_kind` in their metadata.
|
@ematipico Checking on the status of this PR. Anything else needed from my side right now? |
1 similar comment
|
@ematipico Checking on the status of this PR. Anything else needed from my side right now? |
Summary
Fixes #9210
The
useAnchorContentrule was reporting a false positive when an Astro<Image>component with analtattribute was used inside an anchor element. Thehas_accessible_content()function only recognized<img>(case-insensitive) but not Astro's built-in<Image>component, which renders to<img>at build time.This PR recognizes
Image(case-sensitive PascalCase) as an image element in the self-closing element check, scoped to Astro files only so that a<Image>component in Vue or Svelte doesn't incorrectly bypass the rule.Test Plan
cargo test -p biome_html_analyze -- use_anchor_content— all tests pass<a><Image alt="description" /></a>in Astro produces no diagnostic<a><Image /></a>and<a><Image alt="" /></a>produce expected diagnosticsDocs
No documentation changes needed — this is a bug fix for an existing rule with no new options.