eslint-plugin-jsx-a11y
Advanced tools
Comparing version 0.2.0 to 0.2.1
@@ -23,3 +23,3 @@ /** | ||
var type = node.name.name; | ||
if (type.toUpperCase() !== 'IMG') { | ||
if (type !== 'img') { | ||
return; | ||
@@ -26,0 +26,0 @@ } |
@@ -29,12 +29,12 @@ /** | ||
var type = node.name.name; | ||
if (type.toUpperCase() !== 'IMG') { | ||
if (type !== 'img') { | ||
return; | ||
} | ||
var hasAltProp = (0, _hasAttribute2.default)(node.attributes, 'alt'); | ||
var altProp = (0, _hasAttribute2.default)(node.attributes, 'alt'); | ||
var isVisible = (0, _isHiddenFromScreenReader2.default)(node.attributes) === false; | ||
if (Boolean(hasAltProp) && isVisible) { | ||
if (Boolean(altProp) && typeof altProp === 'string' && isVisible) { | ||
var hasRedundancy = REDUNDANT_WORDS.some(function (word) { | ||
return Boolean(hasAltProp.value.value.match(new RegExp(word, 'gi'))); | ||
return Boolean(altProp.match(new RegExp(word, 'gi'))); | ||
}); | ||
@@ -41,0 +41,0 @@ |
@@ -23,3 +23,3 @@ /** | ||
var type = node.name.name; | ||
if (type.toUpperCase() !== 'LABEL') { | ||
if (type !== 'label') { | ||
return; | ||
@@ -26,0 +26,0 @@ } |
@@ -6,6 +6,13 @@ 'use strict'; | ||
}); | ||
var _getAttributeValue = require('./getAttributeValue'); | ||
var _getAttributeValue2 = _interopRequireDefault(_getAttributeValue); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var hasAttribute = function hasAttribute(attributes, attribute) { | ||
var idx = 0; | ||
var value = false; | ||
var hasAttr = attributes.some(function (attr, index) { | ||
var hasAttr = attributes.some(function (attr) { | ||
// If the attributes contain a spread attribute, then skip. | ||
@@ -18,4 +25,6 @@ if (attr.type === 'JSXSpreadAttribute') { | ||
if (attr.name.name.toUpperCase() === attribute.toUpperCase()) { | ||
idx = index; // Keep track of the index. | ||
return true; | ||
value = (0, _getAttributeValue2.default)(attr); | ||
// If the value is undefined, it doesn't really have the attribute. | ||
return value !== undefined; | ||
} | ||
@@ -26,5 +35,5 @@ | ||
return hasAttr ? attributes[idx] : false; | ||
return hasAttr ? value : false; | ||
}; | ||
exports.default = hasAttribute; |
@@ -6,15 +6,14 @@ 'use strict'; | ||
}); | ||
var isHiddenFromScreenReader = function isHiddenFromScreenReader(attributes) { | ||
return attributes.some(function (attribute) { | ||
if (attribute.type === 'JSXSpreadAttribute') { | ||
return false; | ||
} | ||
var name = attribute.name.name.toUpperCase(); | ||
var value = attribute.value && attribute.value.value; | ||
var _hasAttribute = require('./hasAttribute'); | ||
return name === 'ARIA-HIDDEN' && (value === true || value === null); | ||
}); | ||
var _hasAttribute2 = _interopRequireDefault(_hasAttribute); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var isHiddenFromScreenReader = function isHiddenFromScreenReader(attributes) { | ||
var hasAriaHidden = (0, _hasAttribute2.default)(attributes, 'aria-hidden'); | ||
return hasAriaHidden && (hasAriaHidden === true || hasAriaHidden === null); | ||
}; | ||
exports.default = isHiddenFromScreenReader; |
@@ -24,3 +24,3 @@ 'use strict'; | ||
var hasTypeAttr = (0, _hasAttribute2.default)(attributes, 'type'); | ||
return hasTypeAttr ? hasTypeAttr.value.value.toUpperCase() !== 'HIDDEN' : true; | ||
return hasTypeAttr ? hasTypeAttr.toUpperCase() !== 'HIDDEN' : true; | ||
}, | ||
@@ -27,0 +27,0 @@ option: function option() { |
{ | ||
"name": "eslint-plugin-jsx-a11y", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "A static analysis linter of jsx and their accessibility with screen readers.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -18,3 +18,3 @@ /** | ||
const type = node.name.name; | ||
if (type.toUpperCase() !== 'IMG') { | ||
if (type !== 'img') { | ||
return; | ||
@@ -21,0 +21,0 @@ } |
@@ -26,11 +26,11 @@ /** | ||
const type = node.name.name; | ||
if (type.toUpperCase() !== 'IMG') { | ||
if (type !== 'img') { | ||
return; | ||
} | ||
const hasAltProp = hasAttribute(node.attributes, 'alt'); | ||
const altProp = hasAttribute(node.attributes, 'alt'); | ||
const isVisible = isHiddenFromScreenReader(node.attributes) === false; | ||
if (Boolean(hasAltProp) && isVisible) { | ||
const hasRedundancy = REDUNDANT_WORDS.some(word => Boolean(hasAltProp.value.value.match(new RegExp(word, 'gi')))); | ||
if (Boolean(altProp) && typeof altProp === 'string' && isVisible) { | ||
const hasRedundancy = REDUNDANT_WORDS.some(word => Boolean(altProp.match(new RegExp(word, 'gi')))); | ||
@@ -37,0 +37,0 @@ if (hasRedundancy === true) { |
@@ -19,3 +19,3 @@ /** | ||
const type = node.name.name; | ||
if (type.toUpperCase() !== 'LABEL') { | ||
if (type !== 'label') { | ||
return; | ||
@@ -22,0 +22,0 @@ } |
'use strict'; | ||
import getAttributeValue from './getAttributeValue'; | ||
const hasAttribute = (attributes, attribute) => { | ||
let idx = 0; | ||
let value = false; | ||
const hasAttr = attributes.some((attr, index) => { | ||
const hasAttr = attributes.some(attr => { | ||
// If the attributes contain a spread attribute, then skip. | ||
@@ -14,4 +16,6 @@ if (attr.type === 'JSXSpreadAttribute') { | ||
if (attr.name.name.toUpperCase() === attribute.toUpperCase()) { | ||
idx = index; // Keep track of the index. | ||
return true; | ||
value = getAttributeValue(attr); | ||
// If the value is undefined, it doesn't really have the attribute. | ||
return value !== undefined; | ||
} | ||
@@ -22,5 +26,5 @@ | ||
return hasAttr ? attributes[idx] : false; | ||
return hasAttr ? value : false; | ||
}; | ||
export default hasAttribute; |
'use strict'; | ||
const isHiddenFromScreenReader = attributes => ( | ||
attributes.some(attribute => { | ||
if (attribute.type === 'JSXSpreadAttribute') { | ||
return false; | ||
} | ||
import hasAttribute from './hasAttribute'; | ||
const name = attribute.name.name.toUpperCase(); | ||
const value = attribute.value && attribute.value.value; | ||
const isHiddenFromScreenReader = attributes => { | ||
const hasAriaHidden = hasAttribute(attributes, 'aria-hidden'); | ||
return hasAriaHidden && (hasAriaHidden === true || hasAriaHidden === null); | ||
}; | ||
return name === 'ARIA-HIDDEN' && (value === true || value === null); | ||
}) | ||
); | ||
export default isHiddenFromScreenReader; |
@@ -14,3 +14,3 @@ 'use strict'; | ||
const hasTypeAttr = hasAttribute(attributes, 'type'); | ||
return hasTypeAttr ? hasTypeAttr.value.value.toUpperCase() !== 'HIDDEN' : true; | ||
return hasTypeAttr ? hasTypeAttr.toUpperCase() !== 'HIDDEN' : true; | ||
}, | ||
@@ -17,0 +17,0 @@ option: () => true, |
@@ -36,9 +36,17 @@ /** | ||
{ code: '<img alt="foo" />;', parserOptions }, | ||
{ code: '<img alt={"foo"} />;', parserOptions }, | ||
{ code: '<img alt={alt} />;', parserOptions }, | ||
{ code: '<img ALT="foo" />;', parserOptions }, | ||
{ code: '<img ALt="foo" />;', parserOptions }, | ||
{ code: '<img alt="foo" salt={undefined} />;', parserOptions }, | ||
{ code: '<img {...this.props} alt="foo" />', parserOptions }, | ||
{ code: '<a />', parserOptions } | ||
{ code: '<a />', parserOptions }, | ||
{ code: '<img alt={function(e) {} } />', parserOptions }, | ||
{ code: '<div alt={function(e) {} } />', parserOptions }, | ||
{ code: '<img alt={() => void 0} />', parserOptions }, | ||
{ code: '<IMG />', parserOptions } | ||
], | ||
invalid: [ | ||
{ code: '<img />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<img alt={undefined} />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<img src="xyz" />', errors: [ expectedError ], parserOptions }, | ||
@@ -45,0 +53,0 @@ { code: '<img {...this.props} />', errors: [ expectedError ], parserOptions } |
@@ -38,9 +38,13 @@ /** | ||
ruleTester.run('mouseEvents-require-keyEvents', rule, { | ||
ruleTester.run('mouse-events-map-to-key-events', rule, { | ||
valid: [ | ||
{ code: '<div onMouseOver={() => void 0} onFocus={() => void 0} />;', parserOptions }, | ||
{ code: '<div onMouseOver={() => void 0} onFocus={() => void 0} {...props} />;', parserOptions }, | ||
{ code: '<div onMouseOver={handleMouseOver} onFocus={handleFocus} />;', parserOptions }, | ||
{ code: '<div onMouseOver={handleMouseOver} onFocus={handleFocus} {...props} />;', parserOptions }, | ||
{ code: '<div />;', parserOptions }, | ||
{ code: '<div onMouseOut={() => void 0} onBlur={() => void 0} />', parserOptions }, | ||
{ code: '<div onMouseOut={() => void 0} onBlur={() => void 0} {...props} />', parserOptions } | ||
{ code: '<div onMouseOut={() => void 0} onBlur={() => void 0} {...props} />', parserOptions }, | ||
{ code: '<div onMouseOut={handleMouseOut} onBlur={handleOnBlur} />', parserOptions }, | ||
{ code: '<div onMouseOut={handleMouseOut} onBlur={handleOnBlur} {...props} />', parserOptions } | ||
], | ||
@@ -50,2 +54,4 @@ invalid: [ | ||
{ code: '<div onMouseOut={() => void 0} />', errors: [ mouseOutError ], parserOptions }, | ||
{ code: '<div onMouseOver={() => void 0} onFocus={undefined} />;', errors: [ mouseOverError ], parserOptions }, | ||
{ code: '<div onMouseOut={() => void 0} onBlur={undefined} />', errors: [ mouseOutError ], parserOptions }, | ||
{ code: '<div onMouseOver={() => void 0} {...props} />', errors: [ mouseOverError ], parserOptions }, | ||
@@ -52,0 +58,0 @@ { code: '<div onMouseOut={() => void 0} {...props} />', errors: [ mouseOutError ], parserOptions } |
@@ -38,3 +38,4 @@ /** | ||
{ code: '<div />;', parserOptions }, | ||
{ code: '<div {...props} />', parserOptions } | ||
{ code: '<div {...props} />', parserOptions }, | ||
{ code: '<div accessKey={undefined} />', parserOptions } | ||
], | ||
@@ -45,4 +46,6 @@ invalid: [ | ||
{ code: '<div accessKey="h" {...props} />', errors: [ expectedError ], parserOptions }, | ||
{ code: '<div acCesSKeY="y" />', errors: [ expectedError ], parserOptions } | ||
{ code: '<div acCesSKeY="y" />', errors: [ expectedError ], parserOptions }, | ||
{ code: '<div accessKey={"y"} />', errors: [ expectedError ], parserOptions }, | ||
{ code: '<div accessKey={accessKey} />', errors: [ expectedError ], parserOptions } | ||
] | ||
}); |
@@ -34,5 +34,7 @@ /** | ||
ruleTester.run('onClick-uses-role', rule, { | ||
ruleTester.run('onclick-uses-role', rule, { | ||
valid: [ | ||
{ code: '<div onClick={() => void 0} role="button" />;', parserOptions }, | ||
{ code: '<div onClick={() => void 0} role={role} />;', parserOptions }, | ||
{ code: '<div onClick={() => void 0} role={"button"} />;', parserOptions }, | ||
{ code: '<div onClick={() => void 0} role="button" {...props} />;', parserOptions }, | ||
@@ -43,2 +45,3 @@ { code: '<div className="foo" />;', parserOptions }, | ||
{ code: '<div onClick={() => void 0} role="button" aria-hidden={false} />;', parserOptions }, | ||
{ code: '<div onClick={() => void 0} role="button" aria-hidden={undefined} />;', parserOptions }, | ||
{ code: '<input type="text" onClick={() => void 0} />', parserOptions }, | ||
@@ -57,2 +60,3 @@ { code: '<input onClick={() => void 0} />', parserOptions }, | ||
{ code: '<div onClick={() => void 0} />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<div onClick={() => void 0} role={undefined} />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<div onClick={() => void 0} {...props} />;', errors: [ expectedError ], parserOptions }, | ||
@@ -59,0 +63,0 @@ { code: '<section onClick={() => void 0} />;', errors: [ expectedError ], parserOptions }, |
@@ -34,3 +34,3 @@ /** | ||
ruleTester.run('img-uses-alt', rule, { | ||
ruleTester.run('redundant-alt', rule, { | ||
valid: [ | ||
@@ -42,4 +42,11 @@ { code: '<img alt="foo" />;', parserOptions }, | ||
{ code: '<img {...this.props} alt="foo" />', parserOptions }, | ||
{ code: '<img {...this.props} alt={"foo"} />', parserOptions }, | ||
{ code: '<img {...this.props} alt={alt} />', parserOptions }, | ||
{ code: '<a />', parserOptions }, | ||
{ code: '<img />', parserOptions }, | ||
{ code: '<IMG />', parserOptions }, | ||
{ code: '<img alt={undefined} />', parserOptions }, | ||
{ code: '<img alt={"undefined"} />', parserOptions }, | ||
{ code: '<img alt={() => {}} />', parserOptions }, | ||
{ code: '<img alt={function(e){}} />', parserOptions }, | ||
{ code: '<img aria-hidden={false} alt="Doing cool things." />', parserOptions } | ||
@@ -52,2 +59,3 @@ ], | ||
{ code: '<img alt="PhOtO of friend." />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<img alt={"photo"} />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<img alt="piCTUre of friend." />;', errors: [ expectedError ], parserOptions }, | ||
@@ -54,0 +62,0 @@ { code: '<img alt="imAGE of friend." />;', errors: [ expectedError ], parserOptions }, |
@@ -37,7 +37,12 @@ /** | ||
{ code: '<label htmlFor="foo" />', parserOptions }, | ||
{ code: '<label htmlFor={"foo"} />', parserOptions }, | ||
{ code: '<label htmlFor={foo} />', parserOptions }, | ||
{ code: '<div />', parserOptions }, | ||
{ code: '<label htmlFor="foo">Test!</label>', parserOptions } | ||
{ code: '<label htmlFor="foo">Test!</label>', parserOptions }, | ||
{ code: '<Label />', parserOptions }, // lower-case convention refers to real HTML elements. | ||
{ code: '<Label htmlFor="foo" />', parserOptions } | ||
], | ||
invalid: [ | ||
{ code: '<label id="foo" />', errors: [ expectedError ], parserOptions }, | ||
{ code: '<label htmlFor={undefined} />', errors: [ expectedError ], parserOptions }, | ||
{ code: '<label>First Name</label>', errors: [ expectedError ], parserOptions }, | ||
@@ -44,0 +49,0 @@ { code: '<label {...props}>Foo</label>', errors: [ expectedError ], parserOptions } |
@@ -37,2 +37,3 @@ /** | ||
{ code: '<div onBlur={() => {}} />;', parserOptions }, | ||
{ code: '<div onBlur={handleOnBlur} />;', parserOptions }, | ||
{ code: '<div />;', parserOptions }, | ||
@@ -44,2 +45,3 @@ { code: '<div onBlur={() => {}} onChange={() => {}} />;', parserOptions }, | ||
{ code: '<div onChange={() => {}} />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<div onChange={handleOnChange} />;', errors: [ expectedError ], parserOptions }, | ||
{ code: '<input onChange={() => {}} />', errors: [ expectedError ], parserOptions }, | ||
@@ -46,0 +48,0 @@ { code: '<input onChange={() => {}} {...props} />', errors: [ expectedError ], 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
55311
47
1193