feat(lint): noAccessKey
ADD
internal/compiler/lint/rules/a11y/noAccessKey.test.rjson
+[
+ {
+ filename: "file.tsx"
+ invalid: [
+ "<input accessKey='key' />"
+ "<input accessKey={key} />"
+ ]
+ valid: [
+ "<input />"
+ "<input accessKey={undefined} />"
+ "<Input accessKey={key} />"
+ ]
+}
+ {
+ filename: "file.html"
+ invalid: [
+ "<input accesskey=\"h\" />"
+ ]
+ valid: [
+ "<input />"
+ ]
+}
+]

ADD
internal/compiler/lint/rules/a11y/noAccessKey.ts
+import {descriptions} from "@internal/diagnostics";
+import {createVisitor, signals} from "@internal/compiler";
+import {getJSXAttribute, hasJSXAttribute} from "@internal/js-ast-utils";
+import {isJSXDOMElement} from "@internal/js-ast-utils/isJSXDOMElement";
+import isHTMLElement from "@internal/js-ast-utils/isHTMLElement";
+import hasHTMLAttribute from "@internal/js-ast-utils/hasHTMLAttribute";
+import getHTMLAttribute from "@internal/js-ast-utils/getHTMLAttribute";
+
+export default createVisitor({
+ name: "a11y/noAccessKey",
+
+ enter(path) {
+ const {node} = path;
+
+ if (isHTMLElement(node) && hasHTMLAttribute(node, "accesskey")) {
+ return path.addFixableDiagnostic(
+ {
+ target: getHTMLAttribute(node, "accesskey"),
+ fixed: signals.replace({
+ ...node,
+ attributes: node.attributes.filter((attribute) =>
+ attribute.type !== "HTMLAttribute" ||
+ attribute.name.name !== "accesskey"
+ ),
+ }),
+ },
+ descriptions.LINT.A11_Y_NO_ACCESS_KEY,
+ );
+ } else if (isJSXDOMElement(node) && hasJSXAttribute(node, "accessKey")) {
+ return path.addFixableDiagnostic(
+ {
+ target: getJSXAttribute(node, "accessKey"),
+ fixed: signals.replace({
+ ...node,
+ attributes: node.attributes.filter((attribute) =>
+ attribute.type !== "JSXAttribute" ||
+ attribute.name.name !== "accessKey"
+ ),
+ }),
+ },
+ descriptions.LINT.A11_Y_NO_ACCESS_KEY,
+ );
+ }
+
+ return signals.retain;
+ },
+});

MODIFY
internal/compiler/lint/rules/index.ts
internal/compiler/lint/rules/index.ts
-/* GENERATED:START(hash:cbdd144ad35350b9a2f9b4864c8e217f28ce8a7c,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. */
+/* GENERATED:START(hash:692a7d9340104a574b8395dd0890aaf4e5643933,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. */
+import noAccessKey from "./a11y/noAccessKey";
import noAriaUnsupportedElements from "./a11y/noAriaUnsupportedElements";
import noAutofocus from "./a11y/noAutofocus";
import noDistractingElements from "./a11y/noDistractingElements";
@@ -66,7 +67,6 @@ import useSingleVarDeclarator from "./js/useSingleVarDeclarator";
import useSortedSpecifiers from "./js/useSortedSpecifiers";
import useTemplate from "./js/useTemplate";
import useWhile from "./js/useWhile";
-import noAccessKey from "./jsx-a11y/noAccessKey";
import noOnChange from "./jsx-a11y/noOnChange";
import noRedundantRoles from "./jsx-a11y/noRedundantRoles";
import noTargetBlank from "./jsx-a11y/noTargetBlank";
@@ -119,6 +119,7 @@ import useSimplifiedBooleanExpression from "./ts/useSimplifiedBooleanExpression"
import {AnyVisitor} from "@internal/compiler";
export const lintTransforms: Map<LintRuleName, AnyVisitor> = new Map();
+lintTransforms.set("a11y/noAccessKey", noAccessKey);
lintTransforms.set("a11y/noAriaUnsupportedElements", noAriaUnsupportedElements);
lintTransforms.set("a11y/noAutofocus", noAutofocus);
lintTransforms.set("a11y/noDistractingElements", noDistractingElements);
@@ -195,7 +196,6 @@ lintTransforms.set("js/useSingleVarDeclarator", useSingleVarDeclarator);
lintTransforms.set("js/useSortedSpecifiers", useSortedSpecifiers);
lintTransforms.set("js/useTemplate", useTemplate);
lintTransforms.set("js/useWhile", useWhile);
-lintTransforms.set("jsx-a11y/noAccessKey", noAccessKey);
lintTransforms.set("jsx-a11y/noOnChange", noOnChange);
lintTransforms.set("jsx-a11y/noRedundantRoles", noRedundantRoles);
lintTransforms.set("jsx-a11y/noTargetBlank", noTargetBlank);
@@ -268,6 +268,7 @@ lintTransforms.set(
);
export const lintRuleNames: LintRuleName[] = [
+ "a11y/noAccessKey",
"a11y/noAriaUnsupportedElements",
"a11y/noAutofocus",
"a11y/noDistractingElements",
@@ -335,7 +336,6 @@ export const lintRuleNames: LintRuleName[] = [
"js/useSortedSpecifiers",
"js/useTemplate",
"js/useWhile",
- "jsx-a11y/noAccessKey",
"jsx-a11y/noOnChange",
"jsx-a11y/noRedundantRoles",
"jsx-a11y/noTargetBlank",
@@ -388,6 +388,7 @@ export const lintRuleNames: LintRuleName[] = [
];
export type LintRuleName =
+ | "a11y/noAccessKey"
| "a11y/noAriaUnsupportedElements"
| "a11y/noAutofocus"
| "a11y/noDistractingElements"
@@ -455,7 +456,6 @@ export type LintRuleName =
| "js/useSortedSpecifiers"
| "js/useTemplate"
| "js/useWhile"
- | "jsx-a11y/noAccessKey"
| "jsx-a11y/noOnChange"
| "jsx-a11y/noRedundantRoles"
| "jsx-a11y/noTargetBlank"

DELETE
internal/compiler/lint/rules/jsx-a11y/noAccessKey.test.rjson
-filename: "file.tsx"
-invalid: [
- "<input accessKey='key />"
- "<input accessKey={key} />"
-]
-valid: [
- "<input />"
- "<input accessKey={undefined} />"
- "<Input accessKey={key} />"
-]

DELETE
internal/compiler/lint/rules/jsx-a11y/noAccessKey.ts
-import {descriptions} from "@internal/diagnostics";
-import {createVisitor, signals} from "@internal/compiler";
-import {getJSXAttribute, hasJSXAttribute} from "@internal/js-ast-utils";
-import {isJSXDOMElement} from "@internal/js-ast-utils/isJSXDOMElement";
-
-export default createVisitor({
- name: "jsx-a11y/noAccessKey",
-
- enter(path) {
- const {node} = path;
-
- if (isJSXDOMElement(node) && hasJSXAttribute(node, "accessKey")) {
- return path.addFixableDiagnostic(
- {
- target: getJSXAttribute(node, "accessKey"),
- fixed: signals.replace({
- ...node,
- attributes: node.attributes.filter((attribute) =>
- attribute.type !== "JSXAttribute" ||
- attribute.name.name !== "accessKey"
- ),
- }),
- },
- descriptions.LINT.JSX_A11Y_NO_ACCESS_KEY,
- );
- }
-
- return signals.retain;
- },
-});

MODIFY
internal/compiler/lint/rules/tests.ts
internal/compiler/lint/rules/tests.ts
@@ -12,7 +12,9 @@ type Tests = Dict<{
cases: Test | Test[] | Test[][];
}>;
-/* GENERATED:START(hash:379956f6eedd25af39a14faa3aaad5c35838a6a9,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. */
+/* GENERATED:START(hash:a192f0dce4bfbb2bc18f5fa1632f468802c6ba28,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. */
+// @ts-ignore
+import noAccessKey from "./a11y/noAccessKey.test.rjson";
// @ts-ignore
import noAriaUnsupportedElements from "./a11y/noAriaUnsupportedElements.test.rjson";
// @ts-ignore
@@ -146,8 +148,6 @@ import useTemplate from "./js/useTemplate.test.rjson";
// @ts-ignore
import useWhile from "./js/useWhile.test.rjson";
// @ts-ignore
-import noAccessKey from "./jsx-a11y/noAccessKey.test.rjson";
-// @ts-ignore
import noOnChange from "./jsx-a11y/noOnChange.test.rjson";
// @ts-ignore
import noRedundantRoles from "./jsx-a11y/noRedundantRoles.test.rjson";
@@ -239,6 +239,10 @@ import noPosixInRegularExpression from "./regex/noPosixInRegularExpression.test.
import preferShorthandArrayType from "./ts/preferShorthandArrayType.test.rjson";
export const tests: Tests = {
+ "a11y/noAccessKey": {
+ category: ["lint", "a11y", "noAccessKey"],
+ cases: noAccessKey,
+ },
"a11y/noAriaUnsupportedElements": {
category: ["lint", "a11y", "noAriaUnsupportedElements"],
cases: noAriaUnsupportedElements,
@@ -503,10 +507,6 @@ export const tests: Tests = {
category: ["lint", "js", "useWhile"],
cases: useWhile,
},
- "jsx-a11y/noAccessKey": {
- category: ["lint", "jsx-a11y", "noAccessKey"],
- cases: noAccessKey,
- },
"jsx-a11y/noOnChange": {
category: ["lint", "jsx-a11y", "noOnChange"],
cases: noOnChange,

MODIFY
internal/diagnostics/categories.ts
internal/diagnostics/categories.ts
@@ -103,8 +103,9 @@ type DiagnosticCategoryString = StringConverter<DiagnosticCategory>;
type DiagnosticLintCategoryString = StringConverter<DiagnosticLintCategory>;
-/* GENERATED:START(hash:29617e7b360b4bd3bcfbacd81e8f7fa09ee42291,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. */
+/* GENERATED:START(hash:8d85ea45d90ffc05f8ef743a6c38cf41c8152dba,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. */
export type DiagnosticLintCategory =
+ | ["lint", "a11y", "noAccessKey"]
| ["lint", "a11y", "noAriaUnsupportedElements"]
| ["lint", "a11y", "noAutofocus"]
| ["lint", "a11y", "noDistractingElements"]
@@ -172,7 +173,6 @@ export type DiagnosticLintCategory =
| ["lint", "js", "useSortedSpecifiers"]
| ["lint", "js", "useTemplate"]
| ["lint", "js", "useWhile"]
- | ["lint", "jsx-a11y", "noAccessKey"]
| ["lint", "jsx-a11y", "noOnChange"]
| ["lint", "jsx-a11y", "noRedundantRoles"]
| ["lint", "jsx-a11y", "noTargetBlank"]
@@ -225,6 +225,7 @@ export type DiagnosticLintCategory =
const lintCategoryNameMap: {
[name in DiagnosticLintCategoryString]: DiagnosticLintCategory
} = {
+ "lint/a11y/noAccessKey": ["lint", "a11y", "noAccessKey"],
"lint/a11y/noAriaUnsupportedElements": [
"lint",
"a11y",
@@ -316,7 +317,6 @@ const lintCategoryNameMap: {
"lint/js/useSortedSpecifiers": ["lint", "js", "useSortedSpecifiers"],
"lint/js/useTemplate": ["lint", "js", "useTemplate"],
"lint/js/useWhile": ["lint", "js", "useWhile"],
- "lint/jsx-a11y/noAccessKey": ["lint", "jsx-a11y", "noAccessKey"],
"lint/jsx-a11y/noOnChange": ["lint", "jsx-a11y", "noOnChange"],
"lint/jsx-a11y/noRedundantRoles": ["lint", "jsx-a11y", "noRedundantRoles"],
"lint/jsx-a11y/noTargetBlank": ["lint", "jsx-a11y", "noTargetBlank"],

MODIFY
internal/diagnostics/descriptions/lint.ts
internal/diagnostics/descriptions/lint.ts
@@ -17,6 +17,17 @@ import {addEmphasis, createDiagnosticsCategory, orJoin} from "./index";
import {DIAGNOSTIC_CATEGORIES} from "../categories";
export const lint = createDiagnosticsCategory({
+ A11_Y_NO_ACCESS_KEY: {
+ category: DIAGNOSTIC_CATEGORIES["lint/a11y/noAccessKey"],
+ message: markup`Avoid the <emphasis>accessKey</emphasis> attribute to reduce inconsistencies between keyboard shortcuts and screen reader keyboard comments.`,
+ advice: [
+ {
+ type: "log",
+ category: "info",
+ text: markup`Assigning keyboard shortcuts using the accessKey attribute leads to inconsistent keyboard actions across applications.`,
+ },
+ ],
+ },
CSS_NO_INVALID_GRID_TEMPLATE_AREAS: {
category: DIAGNOSTIC_CATEGORIES["lint/css/noInvalidGridTemplateAreas"],
message: markup`All strings must have the same number of cell tokens`,
@@ -487,18 +498,6 @@ export const lint = createDiagnosticsCategory({
],
},
- JSX_A11Y_NO_ACCESS_KEY: {
- category: DIAGNOSTIC_CATEGORIES["lint/jsx-a11y/noAccessKey"],
- message: markup`Avoid the <emphasis>accessKey</emphasis> attribute to reduce inconsistencies between keyboard shortcuts and screen reader keyboard comments.`,
- advice: [
- {
- type: "log",
- category: "info",
- text: markup`Assigning keyboard shortcuts using the accessKey attribute leads to inconsistent keyboard actions across applications.`,
- },
- ],
- },
-
JSX_A11Y_NO_ON_CHANGE: {
category: DIAGNOSTIC_CATEGORIES["lint/jsx-a11y/noOnChange"],
message: markup`Provide an <emphasis>onBlur</emphasis> event instead of an <emphasis>onChange</emphasis> event unless absolutely necessary.`,

MODIFY
website/src/docs/lint/rules/index.md
website/src/docs/lint/rules/index.md
@@ -11,7 +11,7 @@ eleventyNavigation:
# Rules
-<!-- GENERATED:START(hash:7d439f5d88279866e2e455a537db46efca81646d,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. -->
+<!-- GENERATED:START(hash:a15b06d7208a510b63b27b9c377a353c1b734613,id:main) Everything below is automatically generated. DO NOT MODIFY. Run `./rome run scripts/generated-files/lint-rules` to update. -->
<section>
<h2>JavaScript</h2>
<p>Rule semantics and descriptions taken from <a href="https://eslint.org/">ESLint</a>. See individual rule docs for direct references.</p>
@@ -388,6 +388,13 @@ discard redundant terms or operators in boolean expressions
<p>Rule semantics and descriptions taken from <a href="https://github.com/jsx-eslint/eslint-plugin-jsx-a11y">eslint-plugin-jsx-a11y</a>
and <a href="https://axe-linter.deque.com/">axe Linter</a>. See individual rule docs for direct references.</p>
<div class="rule">
+<h3 data-toc-exclude id="noAccessKey">
+ <a href="/docs/lint/rules/a11y/noAccessKey">noAccessKey</a>
+ <a class="header-anchor" href="#noAccessKey"></a>
+</h3>
+MISSING DOCUMENTATION
+</div>
+<div class="rule">
<h3 data-toc-exclude id="noAriaUnsupportedElements">
<a href="/docs/lint/rules/a11y/noAriaUnsupportedElements">noAriaUnsupportedElements</a>
<a class="header-anchor" href="#noAriaUnsupportedElements"></a>
@@ -504,13 +511,6 @@ check if `lang` attribute is valid
<h2>JSX Accessibility</h2>
<p>Rule semantics and descriptions taken from <a href="https://github.com/jsx-eslint/eslint-plugin-jsx-a11y">eslint-plugin-jsx-a11y</a>. See individual rule docs for direct references.</p>
<div class="rule">
-<h3 data-toc-exclude id="noAccessKey">
- <a href="/docs/lint/rules/jsx-a11y/noAccessKey">noAccessKey</a>
- <a class="header-anchor" href="#noAccessKey"></a>
-</h3>
-enforce that the `accessKey` prop is not used on any element to avoid complications with keyboard commands used by a screenreader
-</div>
-<div class="rule">
<h3 data-toc-exclude id="noOnChange">
<a href="/docs/lint/rules/jsx-a11y/noOnChange">noOnChange</a>
<a class="header-anchor" href="#noOnChange"></a>

RENAME
website/src/docs/lint/rules/jsx-a11y/noAccessKey.md
website/src/docs/lint/rules/js/noAccessKey.md
feat(lint): noAccessKey (#1430)