diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index c1a9d3989a6df..aa6d7efedd7ac 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -234,6 +234,7 @@ mod jsx_a11y { pub mod html_has_lang; pub mod iframe_has_title; pub mod img_redundant_alt; + pub mod no_access_key; pub mod no_autofocus; pub mod scope; pub mod tab_index_no_positive; @@ -450,6 +451,7 @@ oxc_macros::declare_all_lint_rules! { jsx_a11y::html_has_lang, jsx_a11y::iframe_has_title, jsx_a11y::img_redundant_alt, + jsx_a11y::no_access_key, jsx_a11y::no_autofocus, jsx_a11y::scope, jsx_a11y::tab_index_no_positive, diff --git a/crates/oxc_linter/src/rules/jsx_a11y/no_access_key.rs b/crates/oxc_linter/src/rules/jsx_a11y/no_access_key.rs new file mode 100644 index 0000000000000..25aef593b9d1a --- /dev/null +++ b/crates/oxc_linter/src/rules/jsx_a11y/no_access_key.rs @@ -0,0 +1,87 @@ +use oxc_ast::{ + ast::{JSXAttributeItem, JSXAttributeValue, JSXExpression, JSXExpressionContainer}, + AstKind, +}; +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; + +use crate::{context::LintContext, rule::Rule, utils::has_jsx_prop_lowercase, AstNode}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed.")] +#[diagnostic(severity(warning), help("Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications."))] +struct NoAccessKeyDiagnostic(#[label] pub Span); + +#[derive(Debug, Default, Clone)] +pub struct NoAccessKey; + +declare_oxc_lint!( + /// ### What it does + /// Enforces that the `accessKey` prop is not used on any element to avoid complications with keyboard commands used by a screenreader. + /// + /// ### Why is this bad? + /// Access keys are HTML attributes that allow web developers to assign keyboard shortcuts to elements. + /// Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create accessibility complications so to avoid complications, access keys should not be used. + /// + /// ### Example + /// ```javascript + /// // Bad + ///
+ /// + /// // Good + /// + /// ``` + NoAccessKey, + correctness +); + +impl Rule for NoAccessKey { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + let AstKind::JSXOpeningElement(jsx_el) = node.kind() else { return }; + if let Some(JSXAttributeItem::Attribute(attr)) = has_jsx_prop_lowercase(jsx_el, "accessKey") + { + match attr.value.as_ref() { + Some(JSXAttributeValue::StringLiteral(_)) => { + ctx.diagnostic(NoAccessKeyDiagnostic(attr.span)); + } + Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer { + expression: JSXExpression::Expression(expr), + .. + })) => { + if expr.is_identifier_reference() & expr.is_undefined() { + return; + } + ctx.diagnostic(NoAccessKeyDiagnostic(attr.span)); + } + _ => {} + } + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![r";", r"", r""]; + + let fail = vec![ + r#""#, + r#""#, + r#""#, + r#""#, + r#""#, + r"", + r"", + r"", + r"", + r"", + r"", + ]; + + Tester::new_without_config(NoAccessKey::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_access_key.snap b/crates/oxc_linter/src/snapshots/no_access_key.snap new file mode 100644 index 0000000000000..f24e18d0ed407 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_access_key.snap @@ -0,0 +1,82 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_access_key +--- + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ───────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ───────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ───────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ───────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ─────────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ────────────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ─────────────────────────────────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ──────────────────────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ───────────────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ────────────────────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + + ⚠ eslint-plugin-jsx-a11y(no-access-key): No access key attribute allowed. + ╭─[no_access_key.tsx:1:1] + 1 │ + · ────────────────────────────────────── + ╰──── + help: Remove the accessKey attribute. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreaders and keyboard-only users create a11y complications. + +