eslint-plugin-jsx-a11y
Advanced tools
Comparing version 1.2.0 to 1.2.1
@@ -0,1 +1,7 @@ | ||
1.2.1 / 2016-05-19 | ||
================== | ||
- [fix] Avoid testing interactivity of wrapper components with same name but different casing | ||
as DOM elements (such as `Button` vs `button`). | ||
1.2.0 / 2016-05-06 | ||
@@ -2,0 +8,0 @@ ================== |
@@ -44,4 +44,28 @@ # img-has-alt | ||
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.** | ||
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.** For example: | ||
#### Bad | ||
```jsx | ||
function Foo(props) { | ||
return <img {...props} /> | ||
} | ||
``` | ||
#### Good | ||
```jsx | ||
function Foo({ alt, ...props}) { | ||
return <img alt={alt} {...props} /> | ||
} | ||
// OR | ||
function Foo(props) { | ||
const { | ||
alt, | ||
...otherProps | ||
} = props; | ||
return <img alt={alt} {...otherProps} /> | ||
} | ||
``` | ||
### Succeed | ||
@@ -48,0 +72,0 @@ ```jsx |
@@ -45,4 +45,28 @@ # label-has-for | ||
Note that passing props as spread attribute without `htmlFor` explicitly defined will cause this rule to fail. Explicitly pass down `htmlFor` prop for rule to pass. The prop must have an actual value to pass. Use `Label` component above as a reference. **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 `htmlFor` explicitly defined will cause this rule to fail. Explicitly pass down `htmlFor` prop for rule to pass. The prop must have an actual value to pass. Use `Label` component above as a reference. **It is a good thing to explicitly pass props that you expect to be passed for self-documentation.** For example: | ||
#### Bad | ||
```jsx | ||
function Foo(props) { | ||
return <label {...props} /> | ||
} | ||
``` | ||
#### Good | ||
```jsx | ||
function Foo({ htmlFor, ...props}) { | ||
return <label htmlFor={htmlFor} {...props} /> | ||
} | ||
// OR | ||
function Foo(props) { | ||
const { | ||
htmlFor, | ||
...otherProps | ||
} = props; | ||
return <label htmlFor={htmlFor} {...otherProps} /> | ||
} | ||
``` | ||
### Succeed | ||
@@ -49,0 +73,0 @@ ```jsx |
@@ -11,2 +11,4 @@ # onclick-has-focus | ||
This rule will only test low-level DOM components, as we can not deterministically map wrapper JSX components to their correct DOM element. | ||
#### References | ||
@@ -13,0 +15,0 @@ 1. [AX_FOCUS_02](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_02) |
# onclick-has-role | ||
Enforce visible, non-interactive elements with click handlers use role attribute. Visible means that it is not hidden from a screen reader. Examples of non-interactive elements are `div`, `section`, and `a` elements without a href prop. The purpose of the role attribute is to identify to screenreaders the exact function of an element. | ||
Enforce visible, non-interactive elements with click handlers use role attribute. Visible means that it is not hidden from a screen reader. Examples of non-interactive elements are `div`, `section`, and `a` elements without a href prop. The purpose of the role attribute is to identify to screenreaders the exact function of an element. This rule will only test low-level DOM components, as we can not deterministically map wrapper JSX components to their correct DOM element. | ||
@@ -19,2 +19,3 @@ #### References | ||
<div onClick={() => void 0} role="button" aria-hidden /> // This is hidden from screenreader. | ||
<Input onClick={() => void 0} type="hidden" /> // This is a higher-level DOM component | ||
``` | ||
@@ -21,0 +22,0 @@ |
@@ -37,3 +37,3 @@ /** | ||
var nodeType = (0, _getNodeType2.default)(node); | ||
var nodeAttrs = _DOM2.default[nodeType.toUpperCase()]; | ||
var nodeAttrs = _DOM2.default[nodeType]; | ||
var isReservedNodeType = nodeAttrs && nodeAttrs.reserved || false; | ||
@@ -40,0 +40,0 @@ |
{ | ||
"A": {}, | ||
"ABBR": {}, | ||
"ADDRESS": {}, | ||
"AREA": {}, | ||
"ARTICLE": {}, | ||
"ASIDE": {}, | ||
"AUDIO": {}, | ||
"B": {}, | ||
"BASE": { | ||
"a": {}, | ||
"abbr": {}, | ||
"address": {}, | ||
"area": {}, | ||
"article": {}, | ||
"aside": {}, | ||
"audio": {}, | ||
"b": {}, | ||
"base": { | ||
"reserved": true | ||
}, | ||
"BDI": {}, | ||
"BDO": {}, | ||
"BIG": {}, | ||
"BLOCKQUOTE": {}, | ||
"BODY": {}, | ||
"BR": {}, | ||
"BUTTON": {}, | ||
"CANVAS": {}, | ||
"CAPTION": {}, | ||
"CITE": {}, | ||
"CODE": {}, | ||
"COL": { | ||
"bdi": {}, | ||
"bdo": {}, | ||
"big": {}, | ||
"blockquote": {}, | ||
"body": {}, | ||
"br": {}, | ||
"button": {}, | ||
"canvas": {}, | ||
"caption": {}, | ||
"cite": {}, | ||
"code": {}, | ||
"col": { | ||
"reserved": true | ||
}, | ||
"COLGROUP": { | ||
"colgroup": { | ||
"reserved": true | ||
}, | ||
"DATA": {}, | ||
"DATALIST": {}, | ||
"DD": {}, | ||
"DEL": {}, | ||
"DETAILS": {}, | ||
"DFN": {}, | ||
"DIALOG": {}, | ||
"DIV": {}, | ||
"DL": {}, | ||
"DT": {}, | ||
"EM": {}, | ||
"EMBED": {}, | ||
"FIELDSET": {}, | ||
"FIGCAPTION": {}, | ||
"FIGURE": {}, | ||
"FOOTER": {}, | ||
"FORM": {}, | ||
"H1": {}, | ||
"H2": {}, | ||
"H3": {}, | ||
"H4": {}, | ||
"H5": {}, | ||
"H6": {}, | ||
"HEAD": { | ||
"data": {}, | ||
"datalist": {}, | ||
"dd": {}, | ||
"del": {}, | ||
"details": {}, | ||
"dfn": {}, | ||
"dialog": {}, | ||
"div": {}, | ||
"dl": {}, | ||
"dt": {}, | ||
"em": {}, | ||
"embed": {}, | ||
"fieldset": {}, | ||
"figcaption": {}, | ||
"figure": {}, | ||
"footer": {}, | ||
"form": {}, | ||
"h1": {}, | ||
"h2": {}, | ||
"h3": {}, | ||
"h4": {}, | ||
"h5": {}, | ||
"h6": {}, | ||
"head": { | ||
"reserved": true | ||
}, | ||
"HEADER": {}, | ||
"HGROUP": {}, | ||
"HR": {}, | ||
"HTML": { | ||
"header": {}, | ||
"hgroup": {}, | ||
"hr": {}, | ||
"html": { | ||
"reserved": true | ||
}, | ||
"I": {}, | ||
"IFRAME": {}, | ||
"IMG": {}, | ||
"INPUT": {}, | ||
"INS": {}, | ||
"KBD": {}, | ||
"KEYGEN": {}, | ||
"LABEL": {}, | ||
"LEGEND": {}, | ||
"LI": {}, | ||
"LINK": { | ||
"i": {}, | ||
"iframe": {}, | ||
"img": {}, | ||
"input": {}, | ||
"ins": {}, | ||
"kbd": {}, | ||
"keygen": {}, | ||
"label": {}, | ||
"legend": {}, | ||
"li": {}, | ||
"link": { | ||
"reserved": true | ||
}, | ||
"MAIN": {}, | ||
"MAP": {}, | ||
"MARK": {}, | ||
"MENU": {}, | ||
"MENUITEM": {}, | ||
"META": { | ||
"main": {}, | ||
"map": {}, | ||
"mark": {}, | ||
"menu": {}, | ||
"menuitem": {}, | ||
"meta": { | ||
"reserved": true | ||
}, | ||
"METER": {}, | ||
"NAV": {}, | ||
"NOSCRIPT": { | ||
"meter": {}, | ||
"nav": {}, | ||
"noscript": { | ||
"reserved": true | ||
}, | ||
"OBJECT": {}, | ||
"OL": {}, | ||
"OPTGROUP": {}, | ||
"OPTION": {}, | ||
"OUTPUT": {}, | ||
"P": {}, | ||
"PARAM": { | ||
"object": {}, | ||
"ol": {}, | ||
"optgroup": {}, | ||
"option": {}, | ||
"output": {}, | ||
"p": {}, | ||
"param": { | ||
"reserved": true | ||
}, | ||
"PICTURE": { | ||
"picture": { | ||
"reserved": true | ||
}, | ||
"PRE": {}, | ||
"PROGRESS": {}, | ||
"Q": {}, | ||
"RP": {}, | ||
"RT": {}, | ||
"RUBY": {}, | ||
"S": {}, | ||
"SAMP": {}, | ||
"SCRIPT": { | ||
"pre": {}, | ||
"progress": {}, | ||
"q": {}, | ||
"rp": {}, | ||
"rt": {}, | ||
"ruby": {}, | ||
"s": {}, | ||
"samp": {}, | ||
"script": { | ||
"reserved": true | ||
}, | ||
"SECTION": {}, | ||
"SELECT": {}, | ||
"SMALL": {}, | ||
"SOURCE": { | ||
"section": {}, | ||
"select": {}, | ||
"small": {}, | ||
"source": { | ||
"reserved": true | ||
}, | ||
"SPAN": {}, | ||
"STRONG": {}, | ||
"STYLE": { | ||
"span": {}, | ||
"strong": {}, | ||
"style": { | ||
"reserved": true | ||
}, | ||
"SUB": {}, | ||
"SUMMARY": {}, | ||
"SUP": {}, | ||
"TABLE": {}, | ||
"TBODY": {}, | ||
"TD": {}, | ||
"TEXTAREA": {}, | ||
"TFOOT": {}, | ||
"TH": {}, | ||
"THEAD": {}, | ||
"TIME": {}, | ||
"TITLE": { | ||
"sub": {}, | ||
"summary": {}, | ||
"sup": {}, | ||
"table": {}, | ||
"tbody": {}, | ||
"td": {}, | ||
"textarea": {}, | ||
"tfoot": {}, | ||
"th": {}, | ||
"thead": {}, | ||
"time": {}, | ||
"title": { | ||
"reserved": true | ||
}, | ||
"TR": {}, | ||
"TRACK": { | ||
"tr": {}, | ||
"track": { | ||
"reserved": true | ||
}, | ||
"U": {}, | ||
"UL": {}, | ||
"VAR": {}, | ||
"VIDEO": {}, | ||
"WBR": {} | ||
"u": {}, | ||
"ul": {}, | ||
"var": {}, | ||
"video": {}, | ||
"wbr": {} | ||
} |
@@ -57,3 +57,3 @@ 'use strict'; | ||
// low-level DOM element this maps to. | ||
if (Object.keys(_DOM2.default).indexOf(tagName.toUpperCase()) === -1) { | ||
if (Object.keys(_DOM2.default).indexOf(tagName) === -1) { | ||
return true; | ||
@@ -60,0 +60,0 @@ } |
{ | ||
"name": "eslint-plugin-jsx-a11y", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"description": "A static analysis linter of jsx and their accessibility with screen readers.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -21,3 +21,3 @@ /** | ||
const nodeType = getNodeType(node); | ||
const nodeAttrs = DOM[nodeType.toUpperCase()]; | ||
const nodeAttrs = DOM[nodeType]; | ||
const isReservedNodeType = nodeAttrs && nodeAttrs.reserved || false; | ||
@@ -24,0 +24,0 @@ |
{ | ||
"A": {}, | ||
"ABBR": {}, | ||
"ADDRESS": {}, | ||
"AREA": {}, | ||
"ARTICLE": {}, | ||
"ASIDE": {}, | ||
"AUDIO": {}, | ||
"B": {}, | ||
"BASE": { | ||
"a": {}, | ||
"abbr": {}, | ||
"address": {}, | ||
"area": {}, | ||
"article": {}, | ||
"aside": {}, | ||
"audio": {}, | ||
"b": {}, | ||
"base": { | ||
"reserved": true | ||
}, | ||
"BDI": {}, | ||
"BDO": {}, | ||
"BIG": {}, | ||
"BLOCKQUOTE": {}, | ||
"BODY": {}, | ||
"BR": {}, | ||
"BUTTON": {}, | ||
"CANVAS": {}, | ||
"CAPTION": {}, | ||
"CITE": {}, | ||
"CODE": {}, | ||
"COL": { | ||
"bdi": {}, | ||
"bdo": {}, | ||
"big": {}, | ||
"blockquote": {}, | ||
"body": {}, | ||
"br": {}, | ||
"button": {}, | ||
"canvas": {}, | ||
"caption": {}, | ||
"cite": {}, | ||
"code": {}, | ||
"col": { | ||
"reserved": true | ||
}, | ||
"COLGROUP": { | ||
"colgroup": { | ||
"reserved": true | ||
}, | ||
"DATA": {}, | ||
"DATALIST": {}, | ||
"DD": {}, | ||
"DEL": {}, | ||
"DETAILS": {}, | ||
"DFN": {}, | ||
"DIALOG": {}, | ||
"DIV": {}, | ||
"DL": {}, | ||
"DT": {}, | ||
"EM": {}, | ||
"EMBED": {}, | ||
"FIELDSET": {}, | ||
"FIGCAPTION": {}, | ||
"FIGURE": {}, | ||
"FOOTER": {}, | ||
"FORM": {}, | ||
"H1": {}, | ||
"H2": {}, | ||
"H3": {}, | ||
"H4": {}, | ||
"H5": {}, | ||
"H6": {}, | ||
"HEAD": { | ||
"data": {}, | ||
"datalist": {}, | ||
"dd": {}, | ||
"del": {}, | ||
"details": {}, | ||
"dfn": {}, | ||
"dialog": {}, | ||
"div": {}, | ||
"dl": {}, | ||
"dt": {}, | ||
"em": {}, | ||
"embed": {}, | ||
"fieldset": {}, | ||
"figcaption": {}, | ||
"figure": {}, | ||
"footer": {}, | ||
"form": {}, | ||
"h1": {}, | ||
"h2": {}, | ||
"h3": {}, | ||
"h4": {}, | ||
"h5": {}, | ||
"h6": {}, | ||
"head": { | ||
"reserved": true | ||
}, | ||
"HEADER": {}, | ||
"HGROUP": {}, | ||
"HR": {}, | ||
"HTML": { | ||
"header": {}, | ||
"hgroup": {}, | ||
"hr": {}, | ||
"html": { | ||
"reserved": true | ||
}, | ||
"I": {}, | ||
"IFRAME": {}, | ||
"IMG": {}, | ||
"INPUT": {}, | ||
"INS": {}, | ||
"KBD": {}, | ||
"KEYGEN": {}, | ||
"LABEL": {}, | ||
"LEGEND": {}, | ||
"LI": {}, | ||
"LINK": { | ||
"i": {}, | ||
"iframe": {}, | ||
"img": {}, | ||
"input": {}, | ||
"ins": {}, | ||
"kbd": {}, | ||
"keygen": {}, | ||
"label": {}, | ||
"legend": {}, | ||
"li": {}, | ||
"link": { | ||
"reserved": true | ||
}, | ||
"MAIN": {}, | ||
"MAP": {}, | ||
"MARK": {}, | ||
"MENU": {}, | ||
"MENUITEM": {}, | ||
"META": { | ||
"main": {}, | ||
"map": {}, | ||
"mark": {}, | ||
"menu": {}, | ||
"menuitem": {}, | ||
"meta": { | ||
"reserved": true | ||
}, | ||
"METER": {}, | ||
"NAV": {}, | ||
"NOSCRIPT": { | ||
"meter": {}, | ||
"nav": {}, | ||
"noscript": { | ||
"reserved": true | ||
}, | ||
"OBJECT": {}, | ||
"OL": {}, | ||
"OPTGROUP": {}, | ||
"OPTION": {}, | ||
"OUTPUT": {}, | ||
"P": {}, | ||
"PARAM": { | ||
"object": {}, | ||
"ol": {}, | ||
"optgroup": {}, | ||
"option": {}, | ||
"output": {}, | ||
"p": {}, | ||
"param": { | ||
"reserved": true | ||
}, | ||
"PICTURE": { | ||
"picture": { | ||
"reserved": true | ||
}, | ||
"PRE": {}, | ||
"PROGRESS": {}, | ||
"Q": {}, | ||
"RP": {}, | ||
"RT": {}, | ||
"RUBY": {}, | ||
"S": {}, | ||
"SAMP": {}, | ||
"SCRIPT": { | ||
"pre": {}, | ||
"progress": {}, | ||
"q": {}, | ||
"rp": {}, | ||
"rt": {}, | ||
"ruby": {}, | ||
"s": {}, | ||
"samp": {}, | ||
"script": { | ||
"reserved": true | ||
}, | ||
"SECTION": {}, | ||
"SELECT": {}, | ||
"SMALL": {}, | ||
"SOURCE": { | ||
"section": {}, | ||
"select": {}, | ||
"small": {}, | ||
"source": { | ||
"reserved": true | ||
}, | ||
"SPAN": {}, | ||
"STRONG": {}, | ||
"STYLE": { | ||
"span": {}, | ||
"strong": {}, | ||
"style": { | ||
"reserved": true | ||
}, | ||
"SUB": {}, | ||
"SUMMARY": {}, | ||
"SUP": {}, | ||
"TABLE": {}, | ||
"TBODY": {}, | ||
"TD": {}, | ||
"TEXTAREA": {}, | ||
"TFOOT": {}, | ||
"TH": {}, | ||
"THEAD": {}, | ||
"TIME": {}, | ||
"TITLE": { | ||
"sub": {}, | ||
"summary": {}, | ||
"sup": {}, | ||
"table": {}, | ||
"tbody": {}, | ||
"td": {}, | ||
"textarea": {}, | ||
"tfoot": {}, | ||
"th": {}, | ||
"thead": {}, | ||
"time": {}, | ||
"title": { | ||
"reserved": true | ||
}, | ||
"TR": {}, | ||
"TRACK": { | ||
"tr": {}, | ||
"track": { | ||
"reserved": true | ||
}, | ||
"U": {}, | ||
"UL": {}, | ||
"VAR": {}, | ||
"VIDEO": {}, | ||
"WBR": {} | ||
"u": {}, | ||
"ul": {}, | ||
"var": {}, | ||
"video": {}, | ||
"wbr": {} | ||
} |
@@ -37,3 +37,3 @@ 'use strict'; | ||
// low-level DOM element this maps to. | ||
if (Object.keys(DOMElements).indexOf(tagName.toUpperCase()) === -1) { | ||
if (Object.keys(DOMElements).indexOf(tagName) === -1) { | ||
return true; | ||
@@ -40,0 +40,0 @@ } |
@@ -41,3 +41,3 @@ /** | ||
return { | ||
code: `<${element.toLowerCase()} ${role} />`, | ||
code: `<${element} ${role} />`, | ||
parserOptions | ||
@@ -52,3 +52,3 @@ }; | ||
return { | ||
code: `<${element.toLowerCase()} ${aria} />`, | ||
code: `<${element} ${aria} />`, | ||
parserOptions | ||
@@ -62,3 +62,3 @@ }; | ||
.map(reservedElem => ({ | ||
code: `<${reservedElem.toLowerCase()} role />`, | ||
code: `<${reservedElem} role />`, | ||
errors: [ errorMessage ], | ||
@@ -71,3 +71,3 @@ parserOptions | ||
.map(reservedElem => ({ | ||
code: `<${reservedElem.toLowerCase()} aria-hidden />`, | ||
code: `<${reservedElem} aria-hidden />`, | ||
errors: [ errorMessage ], | ||
@@ -74,0 +74,0 @@ parserOptions |
@@ -65,3 +65,4 @@ /** | ||
{ code: '<a href="javascript:void(0);" onClick="doSomething();">Click ALL the things!</a>', parserOptions }, | ||
{ code: '<Foo.Bar onClick={() => void 0} aria-hidden={false} />;', parserOptions } | ||
{ code: '<Foo.Bar onClick={() => void 0} aria-hidden={false} />;', parserOptions }, | ||
{ code: '<Input onClick={() => void 0} type="hidden" />;', parserOptions } | ||
], | ||
@@ -68,0 +69,0 @@ |
@@ -57,3 +57,4 @@ /** | ||
{ code: '<input onClick={() => void 0} type="hidden" />;', parserOptions }, | ||
{ code: '<TestComponent onClick={doFoo} />', parserOptions } | ||
{ code: '<TestComponent onClick={doFoo} />', parserOptions }, | ||
{ code: '<Button onClick={doFoo} />', parserOptions } | ||
], | ||
@@ -60,0 +61,0 @@ invalid: [ |
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
370459
11499