Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(aria): generate role metadata #4488

Merged
merged 4 commits into from
Nov 8, 2024
Merged

Conversation

Conaclos
Copy link
Member

@Conaclos Conaclos commented Nov 7, 2024

Summary

Part of #4241.

Since the refactor is already broad and painful enough, I only partially moved the responsibility from biom_aria to biome_aria_metadata for aria roles.

This PR extends the build script of biome_aria_metadata to generate role-related data.
Aria roles are divided between abstract roles and non-abstract (concrete) roles.
Abstract roles cannot be used by a user.
Thus, I created two enumerations to represent roles: AriaAbstraactRole and AriaRole. AriaRole corresponds to all concrete roles.

I introduced the types AriaAbstractRoles, AriaRoles, and AriaAttributes that encapsulate a list of AriaAbstraactRole, AriaRole, or AriaAttribute. This allows us to evolve the internal representation without breaking code that use them.
I currently use a static slice as internal representation. We could switch to bitflags or perfect hash map in the future.

The handwritten roles in biome_aria and the related data are a mix of Aria 1.1, Aria 1.2, and the current draft of Aria 1.3.
To ensure we have the same roles (The mark role was added in the Aria 1.3 draft), I had to switch from Aria 1.2 to the Aria 1.3 draft.
I noticed a trend of removing required attributes in newer versions of ARIA.
Aria 1.1 has more required attributes than Aria 1.2, that is turn has more required attributes than the Aria 1.3 draft.
This explains some changes in the snapshots where previously required attributes are no longer required.

I noticed that the handwritten data omitted deprecated attributes. My current implementation include deprecated attributes because they are still valid. This explains why some code that was flagged as invalid are now valid (e.g. aria-haspopup and aria-invalid are deprecated since Aria 1.2).

Some ARIA rules have slightly different behavior to their ESLInt equivalent.
This led to painful refactoring because I got some snapshot change that looked like regression, but actually was the demonstration of a distinct implementation to the equivalent ESLint rule.

During this refactor, I noticed that I missed a source of data for aria: the WAI-ARIA Graphics Module. This module adds additional roles such as graphics-document. I will add this in a future PR.

As a nice side effect, this PR fixes #4486

Test Plan

I updated the snapshots

@github-actions github-actions bot added A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Nov 7, 2024
@Conaclos Conaclos force-pushed the conaclos/biome-aria-roles branch 5 times, most recently from e9205de to b713542 Compare November 7, 2024 21:13
<link onClick={() => {}} href="#" />

Copy link
Member Author

Choose a reason for hiding this comment

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

Comment on lines -19 to -31
<input type="radio" aria-invalid />
<input type="radio" aria-selected />
<input type="radio" aria-haspopup />
<input type="checkbox" aria-haspopup />
<input type="reset" aria-invalid />
<input type="submit" aria-invalid />
<input type="image" aria-invalid />
<input type="button" aria-invalid />
<menu type="toolbar" aria-haspopup />
<menu type="toolbar" aria-invalid />
<menu type="toolbar" aria-expanded />
<area href="#" aria-invalid />
<a href="#" aria-invalid />
Copy link
Member Author

Choose a reason for hiding this comment

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

I moved its cases in deprecated because these attributes are not forbidden, they are just deprecated.

<img alt="foobar" aria-busy />
<menu type="toolbar" aria-activedescendant />
<button role="tab" aria-selected="true"/>
Copy link
Member Author

Choose a reason for hiding this comment

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

Non regression test for #4486

@@ -23,7 +23,6 @@
<a href="#" aria-live />
<a href="#" aria-owns />
<a href="#" aria-relevant />
<a aria-checked />
Copy link
Member Author

Choose a reason for hiding this comment

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

This is one of the case where our implementation diverges from the ESLint one.
The ESLint rule allows any aria attribute when it is not able to determine a role for an element.

We diverge in two ways:

  • Our code assigns the generic role to a elements without href.
    Conversely, aria-query doesn't assign any implicit role.
    I don't know which approach is the best.
    This is something we should investigate
  • Our rule doesn't give up if a role cannot be determined. Instead, we report any non-global aria attribute as invalid.

Comment on lines -59 to -61
<img alt="" aria-checked />
<img alt="foobar" aria-busy />
<menu type="toolbar" aria-activedescendant />
Copy link
Member Author

Choose a reason for hiding this comment

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

@Conaclos Conaclos changed the title Conaclos/biome aria roles refactor(aria): generate role metadata Nov 7, 2024
@Conaclos Conaclos requested review from a team November 7, 2024 21:24
Comment on lines -98 to -129
match role_name {
"biome_aria::roles::LinkRole" => {
matches!(
aria_attribute,
"aria-expanded" | "aria-haspopup" | "aria-current"
)
}
"biome_aria::roles::ButtonRole" => {
matches!(aria_attribute, "aria-expanded" | "aria-pressed")
}
"biome_aria::roles::CheckboxRole"
| "biome_aria::roles::RadioRole"
| "biome_aria::roles::MenuItemCheckboxRole"
| "biome_aria::roles::MenuItemRadioRole" => {
matches!(aria_attribute, "aria-checked")
}
"biome_aria::roles::ComboBoxRole" => {
matches!(aria_attribute, "aria-expanded")
}
"biome_aria::roles::SliderRole" => {
matches!(
aria_attribute,
"aria-valuemax" | "aria-valuemin" | "aria-valuenow"
)
}
"biome_aria::roles::ListRole" => {
matches!(aria_attribute, "aria-activedescendant")
}
"biome_aria::roles::HeadingRole" => matches!(aria_attribute, "aria-level"),
// This rule is not concerned with the abstract role
"biome_aria::roles::PresentationRole" | "biome_aria::roles::GenericRole" => true,
_ => false,
Copy link
Member Author

Choose a reason for hiding this comment

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

This code seems to patch our handwritten data. We no longer need this :)

Copy link

codspeed-hq bot commented Nov 7, 2024

CodSpeed Performance Report

Merging #4488 will not alter performance

Comparing conaclos/biome-aria-roles (a009d23) with main (3fe9193)

Summary

✅ 99 untouched benchmarks

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.

Great work!!

@Conaclos Conaclos merged commit 27b93c2 into main Nov 8, 2024
13 checks passed
@Conaclos Conaclos deleted the conaclos/biome-aria-roles branch November 8, 2024 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Linter Area: linter L-JavaScript Language: JavaScript and super languages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

💅 Cannot set aria-selected to buttons with tab role
2 participants