clean up altText rule with util methods
MODIFY
packages/@romejs/js-compiler/lint/rules/react/jsxA11yAltText.test.ts
packages/@romejs/js-compiler/lint/rules/react/jsxA11yAltText.test.ts
@@ -18,38 +18,34 @@ test(
// INVALID,
"<img src='foo' />",
"<img {...props} />",
- "<img {...props} alt />",
"<img {...props} alt={undefined} />",
- "<img {...props} alt={`${undefined}`} />",
"<img src='foo' role='presentation' />",
"<img src='foo' role='none' />",
"<object {...props} />",
- "<object aria-label />",
"<object aria-label={undefined} />",
- "<object aria-label={`${undefined}`} />",
"<area {...props} />",
- "<area {...props} alt />",
"<area alt={undefined} />",
- "<area {...props} alt={`${undefined}`} />",
"<input type='image' {...props} />",
- "<input type='image' {...props} alt />",
"<input type='image' {...props} alt={undefined} />",
- "<input type='image' {...props} alt={`${undefined}`} />",
// VALID
+ "<img {...props} alt />",
"<img src='foo' alt='Foo eating a sandwich.' />",
"<img src='foo' alt={'Foo eating a sandwich.'} />",
"<img src='foo' alt={altText} />",
"<img src='foo' alt={`${person} smiling`} />",
"<img src='foo' alt='' />",
+ "<object aria-label />",
"<object aria-label='foo' />",
"<object aria-labelledby='id1' />",
"<object>Meaningful description</object>",
"<object>{hello}</object>",
"<object title='An object' />",
+ "<area {...props} alt />",
"<area aria-label='foo' />",
"<area aria-labelledby='id1' />",
"<area alt='This is descriptive!' />",
+ "<input type='image' {...props} alt />",
"<input type='image' alt='This is descriptive!' />",
"<input type='image' aria-label='foo' />",
"<input type='image' aria-labelledby='id1' />",

MODIFY
packages/@romejs/js-compiler/lint/rules/react/jsxA11yAltText.ts
packages/@romejs/js-compiler/lint/rules/react/jsxA11yAltText.ts
*/
import {Path, TransformExitResult} from "@romejs/js-compiler";
-import {AnyNode, JSXElement} from "@romejs/js-ast";
+import {JSXElement} from "@romejs/js-ast";
import {descriptions} from "@romejs/diagnostics";
+import {
+ getJSXAttribute,
+ hasJSXAttribute,
+ isJSXElement
+} from "@romejs/js-ast-utils";
-function hasUndefinedAltValue(node: AnyNode): boolean {
- if (node.type !== "JSXExpressionContainer") {
+function hasImgAltText(node: JSXElement): boolean {
+ const attr = getJSXAttribute(node, "alt", true);
+ if (attr === undefined) {
return false;
}
return (
- (node.expression.type === "ReferenceIdentifier" &&
- node.expression.name === "undefined") ||
- (node.expression.type === "TemplateLiteral" &&
- node.expression.expressions.some((expression) =>
- expression.type === "ReferenceIdentifier" &&
- expression.name === "undefined"
- ))
- );
-}
-
-function hasImgAltText(node: JSXElement): boolean {
- return node.attributes.some((attr) =>
- attr.type === "JSXAttribute" &&
- attr.name.name === "alt" &&
+ !!(
attr.value &&
- !hasUndefinedAltValue(attr.value)
+ attr.value.type === "StringLiteral" &&
+ attr.value.value === ""
+ ) || hasJSXAttribute(node, "alt")
);
}
function hasObjectAltText(node: JSXElement): boolean {
return (
- node.attributes.some((attr) =>
- attr.type === "JSXAttribute" &&
- attr.name.type === "JSXIdentifier" &&
- /(aria-label)|(aria-labelledby)|(title)/.test(attr.name.name) &&
- attr.value &&
- !hasUndefinedAltValue(attr.value)
- ) || node.children.length > 0
+ hasJSXAttribute(node, "aria-label") ||
+ hasJSXAttribute(node, "aria-labelledby") ||
+ hasJSXAttribute(node, "title") ||
+ node.children.length > 0
);
}
function hasAreaAltText(node: JSXElement): boolean {
- return node.attributes.some((attr) =>
- attr.type === "JSXAttribute" &&
- attr.name.type === "JSXIdentifier" &&
- /(aria-label)|(aria-labelledby)|(alt)|(title)/.test(attr.name.name) &&
- attr.value &&
- !hasUndefinedAltValue(attr.value)
+ return (
+ hasJSXAttribute(node, "aria-label") ||
+ hasJSXAttribute(node, "aria-labelledby") ||
+ hasJSXAttribute(node, "alt") ||
+ hasJSXAttribute(node, "title")
);
}
function hasInputAltText(node: JSXElement): boolean {
- return node.attributes.some((attr) =>
- attr.type === "JSXAttribute" &&
- attr.name.type === "JSXIdentifier" &&
- /(aria-label)|(aria-labelledby)|(alt)|(title)/.test(attr.name.name) &&
- attr.value &&
- !hasUndefinedAltValue(attr.value)
+ return (
+ hasJSXAttribute(node, "aria-label") ||
+ hasJSXAttribute(node, "aria-labelledby") ||
+ hasJSXAttribute(node, "alt") ||
+ hasJSXAttribute(node, "title")
);
}
function hasTypeImage(node: JSXElement): boolean {
- return node.attributes.some((attr) =>
- attr.type === "JSXAttribute" &&
- attr.name.name === "type" &&
+ const attr = getJSXAttribute(node, "type");
+ if (attr === undefined) {
+ return false;
+ }
+ return !!(
attr.value &&
attr.value.type === "StringLiteral" &&
attr.value.value === "image"
@@ -86,20 +78,19 @@ export default {
}
if (
- (node.name.name === "img" && !hasImgAltText(node)) ||
- (node.name.name === "object" && !hasObjectAltText(node)) ||
- (node.name.name === "area" && !hasAreaAltText(node)) ||
- (node.name.name === "input" &&
+ (isJSXElement(node, "img") && !hasImgAltText(node)) ||
+ (isJSXElement(node, "object") && !hasObjectAltText(node)) ||
+ (isJSXElement(node, "area") && !hasAreaAltText(node)) ||
+ (isJSXElement(node, "input") &&
hasTypeImage(node) &&
!hasInputAltText(node))
) {
path.context.addNodeDiagnostic(
node,
- descriptions.LINT.JSX_A11Y_ALT_TEXT,
+ descriptions.LINT.JSX_A11Y_ALT_TEXT
);
}
}
-
return node;
- },
+ }
};

clean up altText rule with util methods