eslint-plugin-jsx-a11y
Advanced tools
Comparing version 0.6.1 to 0.6.2
@@ -44,3 +44,3 @@ # img-uses-alt | ||
Note that passing props as spread attribute without `alt` explicitly defined will cause this rule to fail. Explicitly pass down `alt` prop for rule to pass. The prop must have an actual value to pass. Use `Image` component above as a reference for destructuring and applying the prop. **It is a good thing to explicitly pass props that you expect to be passed for self-documentation.** | ||
Note that passing props as spread attribute without `alt` explicitly defined will cause this rule to fail. Explicitly pass down `alt` prop or use `role="presentation"` for rule to pass. Use `Image` component above as a reference for destructuring and applying the prop. **It is a good thing to explicitly pass props that you expect to be passed for self-documentation.** | ||
@@ -53,3 +53,4 @@ ### Succeed | ||
<img src="foo" alt={`${person} smiling`} /> | ||
<img src="foo" alt="" role="presentation" /> <!-- Alt text can be an empty string if `role="presentation"` --> | ||
<img src="foo" alt="" /> | ||
<img src="foo" role="presentation" /> | ||
``` | ||
@@ -56,0 +57,0 @@ |
@@ -5,2 +5,4 @@ # valid-aria-role | ||
[AX_ARIA_01](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_aria_01) | ||
## Rule details | ||
@@ -7,0 +9,0 @@ |
@@ -36,2 +36,10 @@ /** | ||
var hasRoleProp = (0, _hasAttribute2.default)(node.attributes, 'role'); | ||
var roleValue = (0, _getAttributeValue2.default)(hasRoleProp); | ||
var isPresentation = hasRoleProp && roleValue.toLowerCase() === 'presentation'; | ||
if (isPresentation) { | ||
return; | ||
} | ||
var hasAltProp = (0, _hasAttribute2.default)(node.attributes, 'alt'); | ||
@@ -43,3 +51,3 @@ | ||
node: node, | ||
message: nodeType + ' elements must have an alt prop.' | ||
message: nodeType + ' elements must have an alt prop or use role="presentation".' | ||
}); | ||
@@ -50,21 +58,13 @@ return; | ||
// Check if alt prop is undefined. | ||
var altProp = (0, _getAttributeValue2.default)(hasAltProp); | ||
var altValue = (0, _getAttributeValue2.default)(hasAltProp); | ||
// Check if alt prop is "" | ||
var emptyAlt = hasAltProp && hasAltProp.value && hasAltProp.value.type === 'Literal' && hasAltProp.value.value === ""; | ||
if (altValue || altValue === '') { | ||
return; | ||
} | ||
var hasRoleProp = (0, _hasAttribute2.default)(node.attributes, 'role'); | ||
var roleProp = (0, _getAttributeValue2.default)(hasRoleProp); | ||
// Allow altProp to be "" if `role="presentation"` is present. | ||
var isValid = altProp || emptyAlt && hasRoleProp && roleProp.toUpperCase() === 'PRESENTATION'; | ||
// Undefined alt prop error. | ||
if (!isValid) { | ||
context.report({ | ||
node: node, | ||
message: nodeType + ' alt prop must have a value. You can set alt="" if role="presentation" is applied.' | ||
}); | ||
return; | ||
} | ||
context.report({ | ||
node: node, | ||
message: 'Invalid alt value for ' + nodeType + '. Use alt="" or role="presentation" for presentational images.' | ||
}); | ||
} | ||
@@ -71,0 +71,0 @@ }; |
@@ -15,3 +15,3 @@ 'use strict'; | ||
if (value.type === 'Literal') { | ||
return value.value === "" ? undefined : value.value; | ||
return value.value; | ||
} else if (value.type === 'Identifier') { | ||
@@ -30,3 +30,3 @@ return value.name === "" ? undefined : value.name; | ||
case 'Literal': | ||
return obj.value === "" ? undefined : obj.value; | ||
return obj.value; | ||
case 'TemplateLiteral': | ||
@@ -33,0 +33,0 @@ return (0, _buildTemplateLiteral2.default)(obj); |
{ | ||
"name": "eslint-plugin-jsx-a11y", | ||
"version": "0.6.1", | ||
"version": "0.6.2", | ||
"description": "A static analysis linter of jsx and their accessibility with screen readers.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -25,2 +25,10 @@ /** | ||
const hasRoleProp = hasAttribute(node.attributes, 'role'); | ||
const roleValue = getAttributeValue(hasRoleProp); | ||
const isPresentation = hasRoleProp && roleValue.toLowerCase() === 'presentation'; | ||
if (isPresentation) { | ||
return; | ||
} | ||
const hasAltProp = hasAttribute(node.attributes, 'alt'); | ||
@@ -32,3 +40,3 @@ | ||
node, | ||
message: `${nodeType} elements must have an alt prop.` | ||
message: `${nodeType} elements must have an alt prop or use role="presentation".` | ||
}); | ||
@@ -39,23 +47,14 @@ return; | ||
// Check if alt prop is undefined. | ||
const altProp = getAttributeValue(hasAltProp); | ||
const altValue = getAttributeValue(hasAltProp); | ||
// Check if alt prop is "" | ||
const emptyAlt = hasAltProp && hasAltProp.value | ||
&& hasAltProp.value.type === 'Literal' | ||
&& hasAltProp.value.value === ""; | ||
if (altValue || altValue === '') { | ||
return; | ||
} | ||
const hasRoleProp = hasAttribute(node.attributes, 'role'); | ||
const roleProp = getAttributeValue(hasRoleProp); | ||
// Allow altProp to be "" if `role="presentation"` is present. | ||
const isValid = altProp || (emptyAlt && hasRoleProp && roleProp.toUpperCase() === 'PRESENTATION'); | ||
// Undefined alt prop error. | ||
if (!isValid) { | ||
context.report({ | ||
node, | ||
message: `${nodeType} alt prop must have a value. You can set alt="" if role="presentation" is applied.` | ||
}); | ||
return; | ||
} | ||
context.report({ | ||
node, | ||
message: | ||
`Invalid alt value for ${nodeType}. Use alt="" or role="presentation" for presentational images.` | ||
}); | ||
} | ||
@@ -62,0 +61,0 @@ }); |
@@ -7,3 +7,3 @@ 'use strict'; | ||
if (value.type === 'Literal') { | ||
return value.value === "" ? undefined : value.value; | ||
return value.value; | ||
} else if (value.type === 'Identifier') { | ||
@@ -21,3 +21,3 @@ return value.name === "" ? undefined : value.name; | ||
case 'Literal': | ||
return obj.value === "" ? undefined : obj.value; | ||
return obj.value; | ||
case 'TemplateLiteral': | ||
@@ -24,0 +24,0 @@ return buildTemplateLiteral(obj); |
@@ -28,15 +28,12 @@ /** | ||
const customMissingPropError = type => ({ | ||
message: `${type} elements must have an alt prop.`, | ||
const missingPropError = type => ({ | ||
message: `${type} elements must have an alt prop or use role="presentation".`, | ||
type: 'JSXOpeningElement' | ||
}); | ||
const customAltValueError = type => ({ | ||
message: `${type} alt prop must have a value. You can set alt="" if role="presentation" is applied.`, | ||
const altValueError = type => ({ | ||
message: `Invalid alt value for ${type}. Use alt="" or role="presentation" for presentational images.`, | ||
type: 'JSXOpeningElement' | ||
}); | ||
const expectedMissingPropError = customMissingPropError('img'); | ||
const expectedAltValueError = customAltValueError('img'); | ||
const string = [ 'Avatar' ]; | ||
@@ -69,7 +66,11 @@ const array = [ [ 'Thumbnail', 'Image' ] ]; | ||
{ code: '<img alt={foo.bar() || ""} />', parserOptions }, | ||
{ code: '<img alt="" role="presentation" />', parserOptions }, // Allow alt to be undefined if role="presentation" | ||
{ code: '<img alt="" />', parserOptions }, | ||
{ code: '<img alt=" " />', parserOptions }, | ||
{ code: '<img alt="" role="presentation" />', parserOptions }, | ||
{ code: '<img alt="" role={`presentation`} />', parserOptions }, | ||
{ code: '<img alt="" role={"presentation"} />', parserOptions }, | ||
{ code: '<img role="presentation" />;', parserOptions }, | ||
{ code: '<img alt={undefined} role="presentation" />;', parserOptions }, | ||
{ code: '<img alt role="presentation" />;', parserOptions }, | ||
{ code: '<img alt="this is lit..." role="presentation" />', parserOptions }, | ||
{ code: '<img alt=" " />', parserOptions }, // For decorative images. | ||
@@ -91,2 +92,3 @@ // CUSTOM ELEMENT TESTS FOR STRING OPTION | ||
{ code: '<Avatar alt={alt || "foo" } />', options: string, parserOptions }, | ||
{ code: '<Avatar alt="" />', options: string, parserOptions }, | ||
@@ -125,13 +127,9 @@ // CUSTOM ELEMENT TESTS FOR ARRAY OPTION TESTS | ||
// DEFAULT ELEMENT 'img' TESTS | ||
{ code: '<img />;', errors: [ expectedMissingPropError ], parserOptions }, | ||
{ code: '<img alt />;', errors: [ expectedAltValueError ], parserOptions }, | ||
{ code: '<img alt={undefined} />;', errors: [ expectedAltValueError ], parserOptions }, | ||
{ code: '<img alt={`${undefined}`} />;', errors: [ expectedAltValueError ], parserOptions }, | ||
{ code: '<img alt="" />;', errors: [ expectedAltValueError ], parserOptions }, | ||
{ code: '<img role="presentation" />;', errors: [ expectedMissingPropError ], parserOptions }, | ||
{ code: '<img alt={undefined} role="presentation" />;', errors: [ expectedAltValueError ], parserOptions }, | ||
{ code: '<img alt role="presentation" />;', errors: [ expectedAltValueError ], parserOptions }, | ||
{ code: '<img src="xyz" />', errors: [ expectedMissingPropError ], parserOptions }, | ||
{ code: '<img {...this.props} />', errors: [ expectedMissingPropError ], parserOptions }, | ||
{ code: '<img alt={false || false} />', errors: [ expectedAltValueError ], parserOptions }, | ||
{ code: '<img />;', errors: [ missingPropError('img') ], parserOptions }, | ||
{ code: '<img alt />;', errors: [ altValueError('img') ], parserOptions }, | ||
{ code: '<img alt={undefined} />;', errors: [ altValueError('img') ], parserOptions }, | ||
{ code: '<img alt={`${undefined}`} />;', errors: [ altValueError('img') ], parserOptions }, | ||
{ code: '<img src="xyz" />', errors: [ missingPropError('img') ], parserOptions }, | ||
{ code: '<img {...this.props} />', errors: [ missingPropError('img') ], parserOptions }, | ||
{ code: '<img alt={false || false} />', errors: [ altValueError('img') ], parserOptions }, | ||
@@ -141,24 +139,23 @@ // CUSTOM ELEMENT TESTS FOR STRING OPTION | ||
code: '<Avatar />;', | ||
errors: [ customMissingPropError('Avatar') ], | ||
errors: [ missingPropError('Avatar') ], | ||
options: string, | ||
parserOptions | ||
}, | ||
{ code: '<Avatar alt />;', errors: [ customAltValueError('Avatar') ], options: string, parserOptions }, | ||
{ code: '<Avatar alt={undefined} />;', errors: [ customAltValueError('Avatar') ], options: string, parserOptions }, | ||
{ code: '<Avatar alt />;', errors: [ altValueError('Avatar') ], options: string, parserOptions }, | ||
{ code: '<Avatar alt={undefined} />;', errors: [ altValueError('Avatar') ], options: string, parserOptions }, | ||
{ | ||
code: '<Avatar alt={`${undefined}`} />;', | ||
errors: [ customAltValueError('Avatar') ], | ||
errors: [ altValueError('Avatar') ], | ||
options: string, | ||
parserOptions | ||
}, | ||
{ code: '<Avatar alt="" />;', errors: [ customAltValueError('Avatar') ], options: string, parserOptions }, | ||
{ code: '<Avatar src="xyz" />', errors: [ customMissingPropError('Avatar') ], options: string, parserOptions }, | ||
{ code: '<Avatar {...this.props} />', errors: [ customMissingPropError('Avatar') ], options: string, parserOptions }, | ||
{ code: '<Avatar src="xyz" />', errors: [ missingPropError('Avatar') ], options: string, parserOptions }, | ||
{ code: '<Avatar {...this.props} />', errors: [ missingPropError('Avatar') ], options: string, parserOptions }, | ||
// CUSTOM ELEMENT TESTS FOR ARRAY OPTION TESTS | ||
{ code: '<Thumbnail />;', errors: [ customMissingPropError('Thumbnail') ], options: array, parserOptions }, | ||
{ code: '<Thumbnail alt />;', errors: [ customAltValueError('Thumbnail') ], options: array, parserOptions }, | ||
{ code: '<Thumbnail />;', errors: [ missingPropError('Thumbnail') ], options: array, parserOptions }, | ||
{ code: '<Thumbnail alt />;', errors: [ altValueError('Thumbnail') ], options: array, parserOptions }, | ||
{ | ||
code: '<Thumbnail alt={undefined} />;', | ||
errors: [ customAltValueError('Thumbnail') ], | ||
errors: [ altValueError('Thumbnail') ], | ||
options: array, | ||
@@ -169,22 +166,20 @@ parserOptions | ||
code: '<Thumbnail alt={`${undefined}`} />;', | ||
errors: [ customAltValueError('Thumbnail') ], | ||
errors: [ altValueError('Thumbnail') ], | ||
options: array, | ||
parserOptions | ||
}, | ||
{ code: '<Thumbnail alt="" />;', errors: [ customAltValueError('Thumbnail') ], options: array, parserOptions }, | ||
{ code: '<Thumbnail src="xyz" />', errors: [ customMissingPropError('Thumbnail') ], options: array, parserOptions }, | ||
{ code: '<Thumbnail src="xyz" />', errors: [ missingPropError('Thumbnail') ], options: array, parserOptions }, | ||
{ | ||
code: '<Thumbnail {...this.props} />', | ||
errors: [ customMissingPropError('Thumbnail') ], | ||
errors: [ missingPropError('Thumbnail') ], | ||
options: array, | ||
parserOptions | ||
}, | ||
{ code: '<Image />;', errors: [ customMissingPropError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image alt />;', errors: [ customAltValueError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image alt={undefined} />;', errors: [ customAltValueError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image alt={`${undefined}`} />;', errors: [ customAltValueError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image alt="" />;', errors: [ customAltValueError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image src="xyz" />', errors: [ customMissingPropError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image {...this.props} />', errors: [ customMissingPropError('Image') ], options: array, parserOptions } | ||
{ code: '<Image />;', errors: [ missingPropError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image alt />;', errors: [ altValueError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image alt={undefined} />;', errors: [ altValueError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image alt={`${undefined}`} />;', errors: [ altValueError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image src="xyz" />', errors: [ missingPropError('Image') ], options: array, parserOptions }, | ||
{ code: '<Image {...this.props} />', errors: [ missingPropError('Image') ], options: array, parserOptions } | ||
] | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
108637
63
2140