web 3d图形渲染器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
18 KiB

  1. <p align="center">
  2. <a href="https://travis-ci.com/github/jsx-eslint/eslint-plugin-jsx-a11y">
  3. <img src="https://travis-ci.com/jsx-eslint/eslint-plugin-jsx-a11y.svg?branch=master"
  4. alt="build status">
  5. </a>
  6. <a href="https://npmjs.org/package/eslint-plugin-jsx-a11y">
  7. <img src="https://img.shields.io/npm/v/eslint-plugin-jsx-a11y.svg"
  8. alt="npm version">
  9. </a>
  10. <a href="https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/LICENSE.md">
  11. <img src="https://img.shields.io/npm/l/eslint-plugin-jsx-a11y.svg"
  12. alt="license">
  13. </a>
  14. <a href='https://coveralls.io/github/evcohen/eslint-plugin-jsx-a11y?branch=master'>
  15. <img src='https://coveralls.io/repos/github/evcohen/eslint-plugin-jsx-a11y/badge.svg?branch=master' alt='Coverage Status' />
  16. </a>
  17. <a href='https://npmjs.org/package/eslint-plugin-jsx-a11y'>
  18. <img src='https://img.shields.io/npm/dt/eslint-plugin-jsx-a11y.svg'
  19. alt='Total npm downloads' />
  20. </a>
  21. </p>
  22. <a href='https://tidelift.com/subscription/pkg/npm-eslint-plugin-jsx-a11y?utm_source=npm-eslint-plugin-jsx-a11y&utm_medium=referral&utm_campaign=readme'>Get professional support for eslint-plugin-jsx-a11y on Tidelift</a>
  23. # eslint-plugin-jsx-a11y
  24. Static AST checker for accessibility rules on JSX elements.
  25. #### *Read this in [other languages](https://github.com/ari-os310/eslint-plugin-jsx-a11y/blob/master/translations/Translations.md).*
  26. [Mexican Spanish🇲🇽](https://github.com/ari-os310/eslint-plugin-jsx-a11y/blob/master/translations/README.mx.md)
  27. ## Why?
  28. Ryan Florence built out this awesome runtime-analysis tool called [react-a11y](https://github.com/reactjs/react-a11y). It is super useful. However, since you're probably already using linting in your project, this plugin comes for free and closer to the actual development process. Pairing this plugin with an editor lint plugin, you can bake accessibility standards into your application in real-time.
  29. **Note**: This project does not *replace* react-a11y, but can and should be used in conjunction with it. Static analysis tools cannot determine values of variables that are being placed in props before runtime, so linting will not fail if that value is undefined and/or does not pass the lint rule.
  30. ## Installation
  31. **If you are installing this plugin via `eslint-config-airbnb`, please follow [these instructions](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb#eslint-config-airbnb-1).**
  32. You'll first need to install [ESLint](http://eslint.org):
  33. ```sh
  34. # npm
  35. npm install eslint --save-dev
  36. # yarn
  37. yarn add eslint --dev
  38. ```
  39. Next, install `eslint-plugin-jsx-a11y`:
  40. ```sh
  41. # npm
  42. npm install eslint-plugin-jsx-a11y --save-dev
  43. # yarn
  44. yarn add eslint-plugin-jsx-a11y --dev
  45. ```
  46. **Note:** If you installed ESLint globally (using the `-g` flag in npm, or the `global` prefix in yarn) then you must also install `eslint-plugin-jsx-a11y` globally.
  47. ## Usage
  48. Add `jsx-a11y` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
  49. ```json
  50. {
  51. "plugins": [
  52. "jsx-a11y"
  53. ]
  54. }
  55. ```
  56. Then configure the rules you want to use under the rules section.
  57. ```json
  58. {
  59. "rules": {
  60. "jsx-a11y/rule-name": 2
  61. }
  62. }
  63. ```
  64. You can also enable all the recommended or strict rules at once.
  65. Add `plugin:jsx-a11y/recommended` or `plugin:jsx-a11y/strict` in `extends`:
  66. ```json
  67. {
  68. "extends": [
  69. "plugin:jsx-a11y/recommended"
  70. ]
  71. }
  72. ```
  73. ## Supported Rules
  74. - [accessible-emoji](docs/rules/accessible-emoji.md): Enforce emojis are wrapped in `<span>` and provide screenreader access.
  75. - [alt-text](docs/rules/alt-text.md): Enforce all elements that require alternative text have meaningful information to relay back to end user.
  76. - [anchor-has-content](docs/rules/anchor-has-content.md): Enforce all anchors to contain accessible content.
  77. - [anchor-is-valid](docs/rules/anchor-is-valid.md): Enforce all anchors are valid, navigable elements.
  78. - [aria-activedescendant-has-tabindex](docs/rules/aria-activedescendant-has-tabindex.md): Enforce elements with aria-activedescendant are tabbable.
  79. - [aria-props](docs/rules/aria-props.md): Enforce all `aria-*` props are valid.
  80. - [aria-proptypes](docs/rules/aria-proptypes.md): Enforce ARIA state and property values are valid.
  81. - [aria-role](docs/rules/aria-role.md): Enforce that elements with ARIA roles must use a valid, non-abstract ARIA role.
  82. - [aria-unsupported-elements](docs/rules/aria-unsupported-elements.md): Enforce that elements that do not support ARIA roles, states, and properties do not have those attributes.
  83. - [autocomplete-valid](docs/rules/autocomplete-valid.md): Enforce that autocomplete attributes are used correctly.
  84. - [click-events-have-key-events](docs/rules/click-events-have-key-events.md): Enforce a clickable non-interactive element has at least one keyboard event listener.
  85. - [heading-has-content](docs/rules/heading-has-content.md): Enforce heading (`h1`, `h2`, etc) elements contain accessible content.
  86. - [html-has-lang](docs/rules/html-has-lang.md): Enforce `<html>` element has `lang` prop.
  87. - [iframe-has-title](docs/rules/iframe-has-title.md): Enforce iframe elements have a title attribute.
  88. - [img-redundant-alt](docs/rules/img-redundant-alt.md): Enforce `<img>` alt prop does not contain the word "image", "picture", or "photo".
  89. - [interactive-supports-focus](docs/rules/interactive-supports-focus.md): Enforce that elements with interactive handlers like `onClick` must be focusable.
  90. - [label-has-associated-control](docs/rules/label-has-associated-control.md): Enforce that a `label` tag has a text label and an associated control.
  91. - [lang](docs/rules/lang.md): Enforce lang attribute has a valid value.
  92. - [media-has-caption](docs/rules/media-has-caption.md): Enforces that `<audio>` and `<video>` elements must have a `<track>` for captions.
  93. - [mouse-events-have-key-events](docs/rules/mouse-events-have-key-events.md): Enforce that `onMouseOver`/`onMouseOut` are accompanied by `onFocus`/`onBlur` for keyboard-only users.
  94. - [no-access-key](docs/rules/no-access-key.md): Enforce that the `accessKey` prop is not used on any element to avoid complications with keyboard commands used by a screenreader.
  95. - [no-autofocus](docs/rules/no-autofocus.md): Enforce autoFocus prop is not used.
  96. - [no-distracting-elements](docs/rules/no-distracting-elements.md): Enforce distracting elements are not used.
  97. - [no-interactive-element-to-noninteractive-role](docs/rules/no-interactive-element-to-noninteractive-role.md): Interactive elements should not be assigned non-interactive roles.
  98. - [no-noninteractive-element-interactions](docs/rules/no-noninteractive-element-interactions.md): Non-interactive elements should not be assigned mouse or keyboard event listeners.
  99. - [no-noninteractive-element-to-interactive-role](docs/rules/no-noninteractive-element-to-interactive-role.md): Non-interactive elements should not be assigned interactive roles.
  100. - [no-noninteractive-tabindex](docs/rules/no-noninteractive-tabindex.md): `tabIndex` should only be declared on interactive elements.
  101. - [no-onchange](docs/rules/no-onchange.md): Enforce usage of `onBlur` over `onChange` on select menus for accessibility.
  102. - [no-redundant-roles](docs/rules/no-redundant-roles.md): Enforce explicit role property is not the same as implicit/default role property on element.
  103. - [no-static-element-interactions](docs/rules/no-static-element-interactions.md): Enforce that non-interactive, visible elements (such as `<div>`) that have click handlers use the role attribute.
  104. - [role-has-required-aria-props](docs/rules/role-has-required-aria-props.md): Enforce that elements with ARIA roles must have all required attributes for that role.
  105. - [role-supports-aria-props](docs/rules/role-supports-aria-props.md): Enforce that elements with explicit or implicit roles defined contain only `aria-*` properties supported by that `role`.
  106. - [scope](docs/rules/scope.md): Enforce `scope` prop is only used on `<th>` elements.
  107. - [tabindex-no-positive](docs/rules/tabindex-no-positive.md): Enforce `tabIndex` value is not greater than zero.
  108. ### Difference between 'recommended' and 'strict' mode
  109. Rule | Recommended | Strict
  110. ------------ | ------------- | -------------
  111. [accessible-emoji](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/accessible-emoji.md) | error | error
  112. [alt-text](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md) | error | error
  113. [anchor-has-content](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md) | error | error
  114. [anchor-is-valid](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md) | error | error
  115. [aria-activedescendant-has-tabindex](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-activedescendant-has-tabindex.md) | error | error
  116. [aria-props](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-props.md) | error | error
  117. [aria-proptypes](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-proptypes.md) | error | error
  118. [aria-role](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md) | error | error
  119. [aria-unsupported-elements](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-unsupported-elements.md) | error | error
  120. [autocomplete-valid](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/autocomplete-valid.md) | error | error
  121. [click-events-have-key-events](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md) | error | error
  122. [heading-has-content](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md) | error | error
  123. [html-has-lang](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/html-has-lang.md) | error | error
  124. [iframe-has-title](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/iframe-has-title.md) | error | error
  125. [img-redundant-alt](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md) | error | error
  126. [interactive-supports-focus](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/interactive-supports-focus.md) | error | error
  127. [label-has-associated-control](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-associated-control.md) | error | error
  128. [media-has-caption](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/media-has-caption.md) | error | error
  129. [mouse-events-have-key-events](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md) | error | error
  130. [no-access-key](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md) | error | error
  131. [no-autofocus](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md) | error | error
  132. [no-distracting-elements](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-distracting-elements.md) | error | error
  133. [no-interactive-element-to-noninteractive-role](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-interactive-element-to-noninteractive-role.md) | error, with options | error
  134. [no-noninteractive-element-interactions](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-interactions.md) | error, with options | error
  135. [no-noninteractive-element-to-interactive-role](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-element-to-interactive-role.md) | error, with options | error
  136. [no-noninteractive-tabindex](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md) | error, with options | error
  137. [no-onchange](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md) | error | error
  138. [no-redundant-roles](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-redundant-roles.md) | error | error
  139. [no-static-element-interactions](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md) | error, with options | error
  140. [role-has-required-aria-props](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-has-required-aria-props.md) | error | error
  141. [role-supports-aria-props](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/role-supports-aria-props.md) | error | error
  142. [scope](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/scope.md) | error, with options | error
  143. [tabindex-no-positive](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/tabindex-no-positive.md) | error | error
  144. The following rules have extra options when in *recommended* mode:
  145. #### no-interactive-element-to-noninteractive-role
  146. ```js
  147. 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
  148. 'error',
  149. {
  150. tr: ['none', 'presentation'],
  151. },
  152. ]
  153. ```
  154. #### no-noninteractive-element-interactions
  155. ```js
  156. 'jsx-a11y/no-noninteractive-element-interactions': [
  157. 'error',
  158. {
  159. handlers: [
  160. 'onClick',
  161. 'onMouseDown',
  162. 'onMouseUp',
  163. 'onKeyPress',
  164. 'onKeyDown',
  165. 'onKeyUp',
  166. ],
  167. },
  168. ]
  169. ```
  170. #### no-noninteractive-element-to-interactive-role
  171. ```js
  172. 'jsx-a11y/no-noninteractive-element-to-interactive-role': [
  173. 'error',
  174. {
  175. ul: [
  176. 'listbox',
  177. 'menu',
  178. 'menubar',
  179. 'radiogroup',
  180. 'tablist',
  181. 'tree',
  182. 'treegrid',
  183. ],
  184. ol: [
  185. 'listbox',
  186. 'menu',
  187. 'menubar',
  188. 'radiogroup',
  189. 'tablist',
  190. 'tree',
  191. 'treegrid',
  192. ],
  193. li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
  194. table: ['grid'],
  195. td: ['gridcell'],
  196. },
  197. ]
  198. ```
  199. #### no-noninteractive-tabindex
  200. ```js
  201. 'jsx-a11y/no-noninteractive-tabindex': [
  202. 'error',
  203. {
  204. tags: [],
  205. roles: ['tabpanel'],
  206. },
  207. ]
  208. ```
  209. #### no-static-element-interactions
  210. ```js
  211. 'jsx-a11y/no-noninteractive-element-interactions': [
  212. 'error',
  213. {
  214. handlers: [
  215. 'onClick',
  216. 'onMouseDown',
  217. 'onMouseUp',
  218. 'onKeyPress',
  219. 'onKeyDown',
  220. 'onKeyUp',
  221. ],
  222. },
  223. ]
  224. ```
  225. ## Creating a new rule
  226. If you are developing new rules for this project, you can use the `create-rule`
  227. script to scaffold the new files.
  228. ```
  229. $ ./scripts/create-rule.js my-new-rule
  230. ```
  231. ## Some background on WAI-ARIA, the AX Tree and Browsers
  232. ### Accessibility API
  233. An operating system will provide an accessibility API that maps application state and content onto input/output controllers such as a screen reader, braille device, keyboard, etc.
  234. These APIs were developed as computer interfaces shifted from buffers (which are text-based and inherently quite accessible) to graphical user interfaces (GUIs). The first attempts to make GUIs accessible involved raster image parsing to recognize characters, words, etc. This information was stored in a parallel buffer and made accessible to assistive technology (AT) devices.
  235. As GUIs became more complex, the raster parsing approach became untenable. Accessibility APIs were developed to replace them. Check out [NSAccessibility (AXAPI)](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Protocols/NSAccessibility_Protocol/index.html) for an example. See [Core Accessibility API Mappings 1.1](https://www.w3.org/TR/core-aam-1.1/) for more details.
  236. ### Browsers
  237. Browsers support an Accessibility API on a per operating system basis. For instance, Firefox implements the MSAA accessibility API on Windows, but does not implement the AXAPI on OSX.
  238. ### The Accessibility (AX) Tree & DOM
  239. From the [W3 Core Accessibility API Mappings 1.1](https://www.w3.org/TR/core-aam-1.1/#intro_treetypes)
  240. > The accessibility tree and the DOM tree are parallel structures. Roughly speaking the accessibility tree is a subset of the DOM tree. It includes the user interface objects of the user agent and the objects of the document. Accessible objects are created in the accessibility tree for every DOM element that should be exposed to assistive technology, either because it may fire an accessibility event or because it has a property, relationship or feature which needs to be exposed. Generally, if something can be trimmed out it will be, for reasons of performance and simplicity. For example, a `<span>` with just a style change and no semantics may not get its own accessible object, but the style change will be exposed by other means.
  241. Browser vendors are beginning to expose the AX Tree through inspection tools. Chrome has an experiment available to enable their inspection tool.
  242. You can also see a text-based version of the AX Tree in Chrome in the stable release version.
  243. #### Viewing the AX Tree in Chrome
  244. 1. Navigate to `chrome://accessibility/` in Chrome.
  245. 1. Toggle the `accessibility off` link for any tab that you want to inspect.
  246. 1. A link labeled `show accessibility tree` will appear; click this link.
  247. 1. Balk at the wall of text that gets displayed, but then regain your conviction.
  248. 1. Use the browser's find command to locate strings and values in the wall of text.
  249. ### Pulling it all together
  250. A browser constructs an AX Tree as a subset of the DOM. ARIA heavily informs the properties of this AX Tree. This AX Tree is exposed to the system level Accessibility API which mediates assistive technology agents.
  251. We model ARIA in the [aria-query](https://github.com/a11yance/aria-query) project. We model AXObjects (that comprise the AX Tree) in the [axobject-query](https://github.com/A11yance/axobject-query) project. The goal of the WAI-ARIA specification is to be a complete declarative interface to the AXObject model. The [in-draft 1.2 version](https://github.com/w3c/aria/issues?q=is%3Aissue+is%3Aopen+label%3A%22ARIA+1.2%22) is moving towards this goal. But until then, we must consider the semantics constructs afforded by ARIA as well as those afforded by the AXObject model (AXAPI) in order to determine how HTML can be used to express user interface affordances to assistive technology users.
  252. ## License
  253. eslint-plugin-jsx-a11y is licensed under the [MIT License](LICENSE.md).