add jsx-a11y/ariaProps
MODIFY
packages/@romejs/compiler/lint/rules/index.ts
packages/@romejs/compiler/lint/rules/index.ts
@@ -57,6 +57,7 @@ import unsafeNegation from "./js/unsafeNegation";
import unusedVariables from "./js/unusedVariables";
import altText from "./jsx-a11y/altText";
import anchorHasContent from "./jsx-a11y/anchorHasContent";
+import ariaProps from "./jsx-a11y/ariaProps";
import ariaUnsupportedElements from "./jsx-a11y/ariaUnsupportedElements";
import clickEventsHaveKeyEvents from "./jsx-a11y/clickEventsHaveKeyEvents";
import headingHasContent from "./jsx-a11y/headingHasContent";
@@ -144,6 +145,7 @@ export const lintTransforms = [
unusedVariables,
altText,
anchorHasContent,
+ ariaProps,
ariaUnsupportedElements,
clickEventsHaveKeyEvents,
headingHasContent,

ADD
packages/@romejs/compiler/lint/rules/jsx-a11y/ariaProps.test.ts
+import {test} from "rome";
+import {testLintMultiple} from "../testHelpers";
+
+test(
+ "jsx a11y aria props",
+ async (t) => {
+ await testLintMultiple(
+ t,
+ [
+ // VALID
+ "<div />",
+ "<div></div>",
+ // needs to have "aria-"
+ "<div aria='wee'></div>",
+ "<div abcARIAdef='true'></div>",
+ "<div fooaria-foobar='true'></div>",
+ "<div fooaria-hidden='true'></div>",
+ "<input type='text' aria-errormessage='foobar' />",
+ // INVALID
+ "<input className='' aria-labell='' />",
+ "<div aria-='foobar' />",
+ "<div aria-labeledby='foobar' />",
+ "<div aria-skldjfaria-klajsd='foobar' />",
+ ],
+ {category: "lint/jsx-a11y/ariaProps"},
+ );
+ },
+);

ADD
packages/@romejs/compiler/lint/rules/jsx-a11y/ariaProps.ts
+import {Path} from "@romejs/compiler";
+import {findClosestStringMatch, toKebabCase} from "@romejs/string-utils";
+import {descriptions} from "@romejs/diagnostics";
+import {TransformExitResult} from "@romejs/compiler/types";
+import {ARIAProperty, ariaPropsMap} from "../ariaHelpers";
+
+export default {
+ name: "jsxA11YAriaProps",
+ enter(path: Path): TransformExitResult {
+ const {node, context} = path;
+
+ if (
+ node.type === "JSXAttribute" &&
+ node.name.type === "JSXIdentifier" &&
+ node.name.name.indexOf("aria-") === 0
+ ) {
+ const ariaPropsArray = Array.from(ariaPropsMap).map((ariaProps) =>
+ ariaProps[0]
+ );
+
+ const closestMatch = findClosestStringMatch(
+ node.name.name,
+ ariaPropsArray,
+ );
+
+ let fixed;
+ if (closestMatch !== undefined) {
+ fixed = {
+ ...node,
+ name: {
+ ...node.name,
+ // React Documentation states that ariaProps should be in kebab-case, not camelCase:
+ // https://reactjs.org/docs/accessibility.html#wai-aria
+ name: toKebabCase(closestMatch),
+ },
+ };
+ }
+
+ const isInvalidAriaProperty = !ariaPropsArray.includes(
+ (node.name.name as ARIAProperty),
+ );
+ if (fixed !== undefined && isInvalidAriaProperty) {
+ return context.addFixableDiagnostic(
+ {
+ old: node,
+ suggestions: [
+ {
+ title: "ARIA Spelling Mistake",
+ description: "",
+ fixed,
+ },
+ ],
+ },
+ descriptions.LINT.JSX_A11Y_ARIA_PROPS(node.name.name),
+ );
+ } else if (isInvalidAriaProperty) {
+ context.addNodeDiagnostic(
+ node,
+ descriptions.LINT.JSX_A11Y_ARIA_PROPS(node.name.name),
+ );
+ }
+ }
+ return node;
+ },
+};

MODIFY
packages/@romejs/diagnostics/categories.ts
packages/@romejs/diagnostics/categories.ts
@@ -143,6 +143,7 @@ type LintDiagnosticCategory =
| "lint/js/unusedVariables"
| "lint/jsx-a11y/altText"
| "lint/jsx-a11y/anchorHasContent"
+ | "lint/jsx-a11y/ariaProps"
| "lint/jsx-a11y/ariaUnsupportedElements"
| "lint/jsx-a11y/clickEventsHaveKeyEvents"
| "lint/jsx-a11y/headingHasContent"

MODIFY
packages/@romejs/diagnostics/descriptions/lint.ts
packages/@romejs/diagnostics/descriptions/lint.ts
@@ -16,6 +16,10 @@ import {buildSuggestionAdvice} from "../helpers";
import {createDiagnosticsCategory, orJoin} from "./index";
export const lint = createDiagnosticsCategory({
+ JSX_A11Y_ARIA_PROPS: (attribute: string) => ({
+ category: "lint/jsx-a11y/ariaProps",
+ message: `<emphasis>${attribute}</emphasis> is an invalid ARIA attribute.`,
+ }),
JSX_A11Y_CLICK_EVENTS_HAVE_KEY_EVENTS: {
category: "lint/jsx-a11y/clickEventsHaveKeyEvents",
message: "Pair the <emphasis>onClick</emphasis> mouse event with the <emphasis>onKeyUp</emphasis>, the <emphasis>onKeyDown</emphasis>, or the <emphasis>onKeyPress</emphasis> keyboard event.",

add jsx-a11y/ariaProps (#518)