@arcaauth/eslint-plugin-jsx-a11y 6.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/.babelrc +17 -0
  2. package/.eslintrc +44 -0
  3. package/CHANGELOG.md +774 -0
  4. package/LICENSE.md +8 -0
  5. package/README.md +423 -0
  6. package/__mocks__/IdentifierMock.js +15 -0
  7. package/__mocks__/JSXAttributeMock.js +39 -0
  8. package/__mocks__/JSXElementMock.js +37 -0
  9. package/__mocks__/JSXExpressionContainerMock.js +15 -0
  10. package/__mocks__/JSXSpreadAttributeMock.js +18 -0
  11. package/__mocks__/JSXTextMock.js +17 -0
  12. package/__mocks__/LiteralMock.js +17 -0
  13. package/__mocks__/genInteractives.js +218 -0
  14. package/__tests__/__util__/axeMapping.js +6 -0
  15. package/__tests__/__util__/helpers/getESLintCoreRule.js +9 -0
  16. package/__tests__/__util__/helpers/parsers.js +186 -0
  17. package/__tests__/__util__/parserOptionsMapper.js +53 -0
  18. package/__tests__/__util__/ruleOptionsMapperFactory.js +33 -0
  19. package/__tests__/index-test.js +40 -0
  20. package/__tests__/src/rules/accessible-emoji-test.js +66 -0
  21. package/__tests__/src/rules/alt-text-test.js +291 -0
  22. package/__tests__/src/rules/anchor-ambiguous-text-test.js +117 -0
  23. package/__tests__/src/rules/anchor-has-content-test.js +54 -0
  24. package/__tests__/src/rules/anchor-is-valid-test.js +532 -0
  25. package/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js +95 -0
  26. package/__tests__/src/rules/aria-props-test.js +69 -0
  27. package/__tests__/src/rules/aria-proptypes-test.js +311 -0
  28. package/__tests__/src/rules/aria-role-test.js +118 -0
  29. package/__tests__/src/rules/aria-unsupported-elements-test.js +75 -0
  30. package/__tests__/src/rules/autocomplete-valid-test.js +77 -0
  31. package/__tests__/src/rules/click-events-have-key-events-test.js +77 -0
  32. package/__tests__/src/rules/control-has-associated-label-test.js +327 -0
  33. package/__tests__/src/rules/heading-has-content-test.js +85 -0
  34. package/__tests__/src/rules/html-has-lang-test.js +42 -0
  35. package/__tests__/src/rules/iframe-has-title-test.js +55 -0
  36. package/__tests__/src/rules/img-redundant-alt-test.js +137 -0
  37. package/__tests__/src/rules/interactive-supports-focus-test.js +267 -0
  38. package/__tests__/src/rules/label-has-associated-control-test.js +243 -0
  39. package/__tests__/src/rules/label-has-for-test.js +235 -0
  40. package/__tests__/src/rules/lang-test.js +59 -0
  41. package/__tests__/src/rules/media-has-caption-test.js +220 -0
  42. package/__tests__/src/rules/mouse-events-have-key-events-test.js +154 -0
  43. package/__tests__/src/rules/no-access-key-test.js +48 -0
  44. package/__tests__/src/rules/no-aria-hidden-on-focusable-test.js +44 -0
  45. package/__tests__/src/rules/no-autofocus-test.js +68 -0
  46. package/__tests__/src/rules/no-distracting-elements-test.js +51 -0
  47. package/__tests__/src/rules/no-interactive-element-to-noninteractive-role-test.js +405 -0
  48. package/__tests__/src/rules/no-noninteractive-element-interactions-test.js +502 -0
  49. package/__tests__/src/rules/no-noninteractive-element-to-interactive-role-test.js +500 -0
  50. package/__tests__/src/rules/no-noninteractive-tabindex-test.js +123 -0
  51. package/__tests__/src/rules/no-onchange-test.js +57 -0
  52. package/__tests__/src/rules/no-redundant-roles-test.js +98 -0
  53. package/__tests__/src/rules/no-static-element-interactions-test.js +501 -0
  54. package/__tests__/src/rules/prefer-tag-over-role-test.js +63 -0
  55. package/__tests__/src/rules/role-has-required-aria-props-test.js +134 -0
  56. package/__tests__/src/rules/role-supports-aria-props-test.js +570 -0
  57. package/__tests__/src/rules/scope-test.js +50 -0
  58. package/__tests__/src/rules/tabindex-no-positive-test.js +55 -0
  59. package/__tests__/src/util/attributesComparator-test.js +91 -0
  60. package/__tests__/src/util/getAccessibleChildText-test.js +174 -0
  61. package/__tests__/src/util/getComputedRole-test.js +71 -0
  62. package/__tests__/src/util/getElementType-test.js +154 -0
  63. package/__tests__/src/util/getExplicitRole-test.js +35 -0
  64. package/__tests__/src/util/getImplicitRole-test.js +25 -0
  65. package/__tests__/src/util/getSuggestion-test.js +33 -0
  66. package/__tests__/src/util/getTabIndex-test.js +85 -0
  67. package/__tests__/src/util/hasAccessibleChild-test.js +157 -0
  68. package/__tests__/src/util/implicitRoles/input-test.js +87 -0
  69. package/__tests__/src/util/implicitRoles/menu-test.js +20 -0
  70. package/__tests__/src/util/implicitRoles/menuitem-test.js +38 -0
  71. package/__tests__/src/util/isAbstractRole-test.js +51 -0
  72. package/__tests__/src/util/isContentEditable-test.js +52 -0
  73. package/__tests__/src/util/isDOMElement-test.js +30 -0
  74. package/__tests__/src/util/isDisabledElement-test.js +88 -0
  75. package/__tests__/src/util/isFocusable-test.js +111 -0
  76. package/__tests__/src/util/isInteractiveElement-test.js +104 -0
  77. package/__tests__/src/util/isInteractiveRole-test.js +59 -0
  78. package/__tests__/src/util/isNonInteractiveElement-test.js +97 -0
  79. package/__tests__/src/util/isNonInteractiveRole-test.js +59 -0
  80. package/__tests__/src/util/isNonLiteralProperty-test.js +52 -0
  81. package/__tests__/src/util/isSemanticRoleElement-test.js +72 -0
  82. package/__tests__/src/util/mayContainChildComponent-test.js +219 -0
  83. package/__tests__/src/util/mayHaveAccessibleLabel-test.js +256 -0
  84. package/__tests__/src/util/parserOptionsMapper-test.js +93 -0
  85. package/__tests__/src/util/schemas-test.js +35 -0
  86. package/docs/rules/accessible-emoji.md +30 -0
  87. package/docs/rules/alt-text.md +168 -0
  88. package/docs/rules/anchor-ambiguous-text.md +91 -0
  89. package/docs/rules/anchor-has-content.md +64 -0
  90. package/docs/rules/anchor-is-valid.md +270 -0
  91. package/docs/rules/aria-activedescendant-has-tabindex.md +52 -0
  92. package/docs/rules/aria-props.md +29 -0
  93. package/docs/rules/aria-proptypes.md +30 -0
  94. package/docs/rules/aria-role.md +51 -0
  95. package/docs/rules/aria-unsupported-elements.md +30 -0
  96. package/docs/rules/autocomplete-valid.md +49 -0
  97. package/docs/rules/click-events-have-key-events.md +28 -0
  98. package/docs/rules/control-has-associated-label.md +113 -0
  99. package/docs/rules/heading-has-content.md +67 -0
  100. package/docs/rules/html-has-lang.md +31 -0
  101. package/docs/rules/iframe-has-title.md +37 -0
  102. package/docs/rules/img-redundant-alt.md +48 -0
  103. package/docs/rules/interactive-supports-focus.md +156 -0
  104. package/docs/rules/label-has-associated-control.md +152 -0
  105. package/docs/rules/label-has-for.md +130 -0
  106. package/docs/rules/lang.md +31 -0
  107. package/docs/rules/media-has-caption.md +48 -0
  108. package/docs/rules/mouse-events-have-key-events.md +58 -0
  109. package/docs/rules/no-access-key.md +30 -0
  110. package/docs/rules/no-aria-hidden-on-focusable.md +37 -0
  111. package/docs/rules/no-autofocus.md +43 -0
  112. package/docs/rules/no-distracting-elements.md +41 -0
  113. package/docs/rules/no-interactive-element-to-noninteractive-role.md +73 -0
  114. package/docs/rules/no-noninteractive-element-interactions.md +145 -0
  115. package/docs/rules/no-noninteractive-element-to-interactive-role.md +76 -0
  116. package/docs/rules/no-noninteractive-tabindex.md +115 -0
  117. package/docs/rules/no-onchange.md +36 -0
  118. package/docs/rules/no-redundant-roles.md +46 -0
  119. package/docs/rules/no-static-element-interactions.md +114 -0
  120. package/docs/rules/prefer-tag-over-role.md +32 -0
  121. package/docs/rules/role-has-required-aria-props.md +31 -0
  122. package/docs/rules/role-supports-aria-props.md +39 -0
  123. package/docs/rules/scope.md +30 -0
  124. package/docs/rules/tabindex-no-positive.md +32 -0
  125. package/lib/configs/flat-config-base.js +11 -0
  126. package/lib/configs/legacy-config-base.js +9 -0
  127. package/lib/index.js +209 -0
  128. package/lib/rules/accessible-emoji.js +63 -0
  129. package/lib/rules/alt-text.js +218 -0
  130. package/lib/rules/anchor-ambiguous-text.js +64 -0
  131. package/lib/rules/anchor-has-content.js +60 -0
  132. package/lib/rules/anchor-is-valid.js +122 -0
  133. package/lib/rules/aria-activedescendant-has-tabindex.js +66 -0
  134. package/lib/rules/aria-props.js +59 -0
  135. package/lib/rules/aria-proptypes.js +114 -0
  136. package/lib/rules/aria-role.js +89 -0
  137. package/lib/rules/aria-unsupported-elements.js +64 -0
  138. package/lib/rules/autocomplete-valid.js +67 -0
  139. package/lib/rules/click-events-have-key-events.js +68 -0
  140. package/lib/rules/control-has-associated-label.js +103 -0
  141. package/lib/rules/heading-has-content.js +61 -0
  142. package/lib/rules/html-has-lang.js +50 -0
  143. package/lib/rules/iframe-has-title.js +50 -0
  144. package/lib/rules/img-redundant-alt.js +88 -0
  145. package/lib/rules/interactive-supports-focus.js +87 -0
  146. package/lib/rules/label-has-associated-control.js +127 -0
  147. package/lib/rules/label-has-for.js +150 -0
  148. package/lib/rules/lang.js +68 -0
  149. package/lib/rules/media-has-caption.js +96 -0
  150. package/lib/rules/mouse-events-have-key-events.js +94 -0
  151. package/lib/rules/no-access-key.js +43 -0
  152. package/lib/rules/no-aria-hidden-on-focusable.js +47 -0
  153. package/lib/rules/no-autofocus.js +62 -0
  154. package/lib/rules/no-distracting-elements.js +54 -0
  155. package/lib/rules/no-interactive-element-to-noninteractive-role.js +81 -0
  156. package/lib/rules/no-noninteractive-element-interactions.js +95 -0
  157. package/lib/rules/no-noninteractive-element-to-interactive-role.js +80 -0
  158. package/lib/rules/no-noninteractive-tabindex.js +109 -0
  159. package/lib/rules/no-onchange.js +52 -0
  160. package/lib/rules/no-redundant-roles.js +86 -0
  161. package/lib/rules/no-static-element-interactions.js +102 -0
  162. package/lib/rules/prefer-tag-over-role.js +75 -0
  163. package/lib/rules/role-has-required-aria-props.js +88 -0
  164. package/lib/rules/role-supports-aria-props.js +78 -0
  165. package/lib/rules/scope.js +58 -0
  166. package/lib/rules/tabindex-no-positive.js +53 -0
  167. package/lib/util/attributesComparator.js +34 -0
  168. package/lib/util/getAccessibleChildText.js +55 -0
  169. package/lib/util/getComputedRole.js +19 -0
  170. package/lib/util/getElementType.js +30 -0
  171. package/lib/util/getExplicitRole.js +27 -0
  172. package/lib/util/getImplicitRole.js +24 -0
  173. package/lib/util/getSuggestion.js +32 -0
  174. package/lib/util/getTabIndex.js +34 -0
  175. package/lib/util/hasAccessibleChild.js +30 -0
  176. package/lib/util/implicitRoles/a.js +17 -0
  177. package/lib/util/implicitRoles/area.js +17 -0
  178. package/lib/util/implicitRoles/article.js +13 -0
  179. package/lib/util/implicitRoles/aside.js +13 -0
  180. package/lib/util/implicitRoles/body.js +13 -0
  181. package/lib/util/implicitRoles/button.js +13 -0
  182. package/lib/util/implicitRoles/datalist.js +13 -0
  183. package/lib/util/implicitRoles/details.js +13 -0
  184. package/lib/util/implicitRoles/dialog.js +13 -0
  185. package/lib/util/implicitRoles/form.js +13 -0
  186. package/lib/util/implicitRoles/h1.js +13 -0
  187. package/lib/util/implicitRoles/h2.js +13 -0
  188. package/lib/util/implicitRoles/h3.js +13 -0
  189. package/lib/util/implicitRoles/h4.js +13 -0
  190. package/lib/util/implicitRoles/h5.js +13 -0
  191. package/lib/util/implicitRoles/h6.js +13 -0
  192. package/lib/util/implicitRoles/hr.js +13 -0
  193. package/lib/util/implicitRoles/img.js +31 -0
  194. package/lib/util/implicitRoles/index.js +82 -0
  195. package/lib/util/implicitRoles/input.js +38 -0
  196. package/lib/util/implicitRoles/li.js +13 -0
  197. package/lib/util/implicitRoles/link.js +17 -0
  198. package/lib/util/implicitRoles/menu.js +19 -0
  199. package/lib/util/implicitRoles/menuitem.js +28 -0
  200. package/lib/util/implicitRoles/meter.js +13 -0
  201. package/lib/util/implicitRoles/nav.js +13 -0
  202. package/lib/util/implicitRoles/ol.js +13 -0
  203. package/lib/util/implicitRoles/option.js +13 -0
  204. package/lib/util/implicitRoles/output.js +13 -0
  205. package/lib/util/implicitRoles/progress.js +13 -0
  206. package/lib/util/implicitRoles/section.js +13 -0
  207. package/lib/util/implicitRoles/select.js +13 -0
  208. package/lib/util/implicitRoles/tbody.js +13 -0
  209. package/lib/util/implicitRoles/textarea.js +13 -0
  210. package/lib/util/implicitRoles/tfoot.js +13 -0
  211. package/lib/util/implicitRoles/thead.js +13 -0
  212. package/lib/util/implicitRoles/ul.js +13 -0
  213. package/lib/util/isAbstractRole.js +23 -0
  214. package/lib/util/isContentEditable.js +13 -0
  215. package/lib/util/isDOMElement.js +15 -0
  216. package/lib/util/isDisabledElement.js +23 -0
  217. package/lib/util/isFocusable.js +23 -0
  218. package/lib/util/isHiddenFromScreenReader.js +26 -0
  219. package/lib/util/isInteractiveElement.js +116 -0
  220. package/lib/util/isInteractiveRole.js +54 -0
  221. package/lib/util/isNonInteractiveElement.js +131 -0
  222. package/lib/util/isNonInteractiveRole.js +55 -0
  223. package/lib/util/isNonLiteralProperty.js +29 -0
  224. package/lib/util/isPresentationRole.js +13 -0
  225. package/lib/util/isSemanticRoleElement.js +54 -0
  226. package/lib/util/mayContainChildComponent.js +50 -0
  227. package/lib/util/mayHaveAccessibleLabel.js +95 -0
  228. package/lib/util/schemas.js +52 -0
  229. package/package.json +120 -0
@@ -0,0 +1,32 @@
1
+ # jsx-a11y/tabindex-no-positive
2
+
3
+ 💼 This rule is enabled in the following configs: ☑️ `recommended`, 🔒 `strict`.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Avoid positive `tabIndex` property values to synchronize the flow of the page with keyboard tab order.
8
+
9
+ ## Rule details
10
+
11
+ This rule takes no arguments.
12
+
13
+ ### Succeed
14
+ ```jsx
15
+ <span tabIndex="0">foo</span>
16
+ <span tabIndex="-1">bar</span>
17
+ <span tabIndex={0}>baz</span>
18
+ ```
19
+
20
+ ### Fail
21
+ ```jsx
22
+ <span tabIndex="5">foo</span>
23
+ <span tabIndex="3">bar</span>
24
+ <span tabIndex="1">baz</span>
25
+ <span tabIndex="2">never really sure what goes after baz</span>
26
+ ```
27
+
28
+ ## Accessibility guidelines
29
+ - [WCAG 2.4.3](https://www.w3.org/WAI/WCAG21/Understanding/focus-order)
30
+
31
+ ### Resources
32
+ - [Chrome Audit Rules, AX_FOCUS_03](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules#ax_focus_03)
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ languageOptions: {
5
+ parserOptions: {
6
+ ecmaFeatures: {
7
+ jsx: true
8
+ }
9
+ }
10
+ }
11
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ parserOptions: {
5
+ ecmaFeatures: {
6
+ jsx: true
7
+ }
8
+ }
9
+ };
package/lib/index.js ADDED
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+
3
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
7
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
8
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
9
+ /* eslint-disable global-require */
10
+ var flatConfigBase = require('./configs/flat-config-base');
11
+ var legacyConfigBase = require('./configs/legacy-config-base');
12
+ var _require = require('../package.json'),
13
+ name = _require.name,
14
+ version = _require.version;
15
+ var allRules = {
16
+ 'accessible-emoji': require('./rules/accessible-emoji'),
17
+ 'alt-text': require('./rules/alt-text'),
18
+ 'anchor-ambiguous-text': require('./rules/anchor-ambiguous-text'),
19
+ 'anchor-has-content': require('./rules/anchor-has-content'),
20
+ 'anchor-is-valid': require('./rules/anchor-is-valid'),
21
+ 'aria-activedescendant-has-tabindex': require('./rules/aria-activedescendant-has-tabindex'),
22
+ 'aria-props': require('./rules/aria-props'),
23
+ 'aria-proptypes': require('./rules/aria-proptypes'),
24
+ 'aria-role': require('./rules/aria-role'),
25
+ 'aria-unsupported-elements': require('./rules/aria-unsupported-elements'),
26
+ 'autocomplete-valid': require('./rules/autocomplete-valid'),
27
+ 'click-events-have-key-events': require('./rules/click-events-have-key-events'),
28
+ 'control-has-associated-label': require('./rules/control-has-associated-label'),
29
+ 'heading-has-content': require('./rules/heading-has-content'),
30
+ 'html-has-lang': require('./rules/html-has-lang'),
31
+ 'iframe-has-title': require('./rules/iframe-has-title'),
32
+ 'img-redundant-alt': require('./rules/img-redundant-alt'),
33
+ 'interactive-supports-focus': require('./rules/interactive-supports-focus'),
34
+ 'label-has-associated-control': require('./rules/label-has-associated-control'),
35
+ 'label-has-for': require('./rules/label-has-for'),
36
+ lang: require('./rules/lang'),
37
+ 'media-has-caption': require('./rules/media-has-caption'),
38
+ 'mouse-events-have-key-events': require('./rules/mouse-events-have-key-events'),
39
+ 'no-access-key': require('./rules/no-access-key'),
40
+ 'no-aria-hidden-on-focusable': require('./rules/no-aria-hidden-on-focusable'),
41
+ 'no-autofocus': require('./rules/no-autofocus'),
42
+ 'no-distracting-elements': require('./rules/no-distracting-elements'),
43
+ 'no-interactive-element-to-noninteractive-role': require('./rules/no-interactive-element-to-noninteractive-role'),
44
+ 'no-noninteractive-element-interactions': require('./rules/no-noninteractive-element-interactions'),
45
+ 'no-noninteractive-element-to-interactive-role': require('./rules/no-noninteractive-element-to-interactive-role'),
46
+ 'no-noninteractive-tabindex': require('./rules/no-noninteractive-tabindex'),
47
+ 'no-onchange': require('./rules/no-onchange'),
48
+ 'no-redundant-roles': require('./rules/no-redundant-roles'),
49
+ 'no-static-element-interactions': require('./rules/no-static-element-interactions'),
50
+ 'prefer-tag-over-role': require('./rules/prefer-tag-over-role'),
51
+ 'role-has-required-aria-props': require('./rules/role-has-required-aria-props'),
52
+ 'role-supports-aria-props': require('./rules/role-supports-aria-props'),
53
+ scope: require('./rules/scope'),
54
+ 'tabindex-no-positive': require('./rules/tabindex-no-positive')
55
+ };
56
+ var recommendedRules = {
57
+ 'jsx-a11y/alt-text': 'error',
58
+ 'jsx-a11y/anchor-ambiguous-text': 'off',
59
+ // TODO: error
60
+ 'jsx-a11y/anchor-has-content': 'error',
61
+ 'jsx-a11y/anchor-is-valid': 'error',
62
+ 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
63
+ 'jsx-a11y/aria-props': 'error',
64
+ 'jsx-a11y/aria-proptypes': 'error',
65
+ 'jsx-a11y/aria-role': 'error',
66
+ 'jsx-a11y/aria-unsupported-elements': 'error',
67
+ 'jsx-a11y/autocomplete-valid': 'error',
68
+ 'jsx-a11y/click-events-have-key-events': 'error',
69
+ 'jsx-a11y/control-has-associated-label': ['off', {
70
+ ignoreElements: ['audio', 'canvas', 'embed', 'input', 'textarea', 'tr', 'video'],
71
+ ignoreRoles: ['grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'row', 'tablist', 'toolbar', 'tree', 'treegrid'],
72
+ includeRoles: ['alert', 'dialog']
73
+ }],
74
+ 'jsx-a11y/heading-has-content': 'error',
75
+ 'jsx-a11y/html-has-lang': 'error',
76
+ 'jsx-a11y/iframe-has-title': 'error',
77
+ 'jsx-a11y/img-redundant-alt': 'error',
78
+ 'jsx-a11y/interactive-supports-focus': ['error', {
79
+ tabbable: ['button', 'checkbox', 'link', 'searchbox', 'spinbutton', 'switch', 'textbox']
80
+ }],
81
+ 'jsx-a11y/label-has-associated-control': 'error',
82
+ 'jsx-a11y/label-has-for': 'off',
83
+ 'jsx-a11y/media-has-caption': 'error',
84
+ 'jsx-a11y/mouse-events-have-key-events': 'error',
85
+ 'jsx-a11y/no-access-key': 'error',
86
+ 'jsx-a11y/no-autofocus': 'error',
87
+ 'jsx-a11y/no-distracting-elements': 'error',
88
+ 'jsx-a11y/no-interactive-element-to-noninteractive-role': ['error', {
89
+ tr: ['none', 'presentation'],
90
+ canvas: ['img']
91
+ }],
92
+ 'jsx-a11y/no-noninteractive-element-interactions': ['error', {
93
+ handlers: ['onClick', 'onError', 'onLoad', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'],
94
+ alert: ['onKeyUp', 'onKeyDown', 'onKeyPress'],
95
+ body: ['onError', 'onLoad'],
96
+ dialog: ['onKeyUp', 'onKeyDown', 'onKeyPress'],
97
+ iframe: ['onError', 'onLoad'],
98
+ img: ['onError', 'onLoad']
99
+ }],
100
+ 'jsx-a11y/no-noninteractive-element-to-interactive-role': ['error', {
101
+ ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
102
+ ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
103
+ li: ['menuitem', 'menuitemradio', 'menuitemcheckbox', 'option', 'row', 'tab', 'treeitem'],
104
+ table: ['grid'],
105
+ td: ['gridcell'],
106
+ fieldset: ['radiogroup', 'presentation']
107
+ }],
108
+ 'jsx-a11y/no-noninteractive-tabindex': ['error', {
109
+ tags: [],
110
+ roles: ['tabpanel'],
111
+ allowExpressionValues: true
112
+ }],
113
+ 'jsx-a11y/no-redundant-roles': 'error',
114
+ 'jsx-a11y/no-static-element-interactions': ['error', {
115
+ allowExpressionValues: true,
116
+ handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp']
117
+ }],
118
+ 'jsx-a11y/role-has-required-aria-props': 'error',
119
+ 'jsx-a11y/role-supports-aria-props': 'error',
120
+ 'jsx-a11y/scope': 'error',
121
+ 'jsx-a11y/tabindex-no-positive': 'error'
122
+ };
123
+ var strictRules = {
124
+ 'jsx-a11y/alt-text': 'error',
125
+ 'jsx-a11y/anchor-has-content': 'error',
126
+ 'jsx-a11y/anchor-is-valid': 'error',
127
+ 'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
128
+ 'jsx-a11y/aria-props': 'error',
129
+ 'jsx-a11y/aria-proptypes': 'error',
130
+ 'jsx-a11y/aria-role': 'error',
131
+ 'jsx-a11y/aria-unsupported-elements': 'error',
132
+ 'jsx-a11y/autocomplete-valid': 'error',
133
+ 'jsx-a11y/click-events-have-key-events': 'error',
134
+ 'jsx-a11y/control-has-associated-label': ['off', {
135
+ ignoreElements: ['audio', 'canvas', 'embed', 'input', 'textarea', 'tr', 'video'],
136
+ ignoreRoles: ['grid', 'listbox', 'menu', 'menubar', 'radiogroup', 'row', 'tablist', 'toolbar', 'tree', 'treegrid'],
137
+ includeRoles: ['alert', 'dialog']
138
+ }],
139
+ 'jsx-a11y/heading-has-content': 'error',
140
+ 'jsx-a11y/html-has-lang': 'error',
141
+ 'jsx-a11y/iframe-has-title': 'error',
142
+ 'jsx-a11y/img-redundant-alt': 'error',
143
+ 'jsx-a11y/interactive-supports-focus': ['error', {
144
+ tabbable: ['button', 'checkbox', 'link', 'progressbar', 'searchbox', 'slider', 'spinbutton', 'switch', 'textbox']
145
+ }],
146
+ 'jsx-a11y/label-has-for': 'off',
147
+ 'jsx-a11y/label-has-associated-control': 'error',
148
+ 'jsx-a11y/media-has-caption': 'error',
149
+ 'jsx-a11y/mouse-events-have-key-events': 'error',
150
+ 'jsx-a11y/no-access-key': 'error',
151
+ 'jsx-a11y/no-autofocus': 'error',
152
+ 'jsx-a11y/no-distracting-elements': 'error',
153
+ 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
154
+ 'jsx-a11y/no-noninteractive-element-interactions': ['error', {
155
+ body: ['onError', 'onLoad'],
156
+ iframe: ['onError', 'onLoad'],
157
+ img: ['onError', 'onLoad']
158
+ }],
159
+ 'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
160
+ 'jsx-a11y/no-noninteractive-tabindex': 'error',
161
+ 'jsx-a11y/no-redundant-roles': 'error',
162
+ 'jsx-a11y/no-static-element-interactions': 'error',
163
+ 'jsx-a11y/role-has-required-aria-props': 'error',
164
+ 'jsx-a11y/role-supports-aria-props': 'error',
165
+ 'jsx-a11y/scope': 'error',
166
+ 'jsx-a11y/tabindex-no-positive': 'error'
167
+ };
168
+
169
+ /** Base plugin object */
170
+ var jsxA11y = {
171
+ meta: {
172
+ name,
173
+ version
174
+ },
175
+ rules: _objectSpread({}, allRules)
176
+ };
177
+
178
+ /**
179
+ * Given a ruleset and optionally a flat config name, generate a config.
180
+ * @param {object} rules - ruleset for this config
181
+ * @param {string} flatConfigName - name for the config if flat
182
+ * @returns Config for this set of rules.
183
+ */
184
+ var createConfig = function createConfig(rules, flatConfigName) {
185
+ return _objectSpread(_objectSpread({}, flatConfigName ? _objectSpread(_objectSpread({}, flatConfigBase), {}, {
186
+ name: "jsx-a11y/".concat(flatConfigName),
187
+ plugins: {
188
+ 'jsx-a11y': jsxA11y
189
+ }
190
+ }) : _objectSpread(_objectSpread({}, legacyConfigBase), {}, {
191
+ plugins: ['jsx-a11y']
192
+ })), {}, {
193
+ rules: _objectSpread({}, rules)
194
+ });
195
+ };
196
+
197
+ // Create configs for the plugin object
198
+ var configs = {
199
+ recommended: createConfig(recommendedRules),
200
+ strict: createConfig(strictRules)
201
+ };
202
+ var flatConfigs = {
203
+ recommended: createConfig(recommendedRules, 'recommended'),
204
+ strict: createConfig(strictRules, 'strict')
205
+ };
206
+ module.exports = _objectSpread(_objectSpread({}, jsxA11y), {}, {
207
+ configs,
208
+ flatConfigs
209
+ });
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _emojiRegex = _interopRequireDefault(require("emoji-regex"));
8
+ var _jsxAstUtils = require("jsx-ast-utils");
9
+ var _safeRegexTest = _interopRequireDefault(require("safe-regex-test"));
10
+ var _schemas = require("../util/schemas");
11
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
12
+ var _isHiddenFromScreenReader = _interopRequireDefault(require("../util/isHiddenFromScreenReader"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
14
+ /**
15
+ * @fileoverview Enforce emojis are wrapped in <span> and provide screen reader access.
16
+ * @author Ethan Cohen
17
+ */
18
+
19
+ // ----------------------------------------------------------------------------
20
+ // Rule Definition
21
+ // ----------------------------------------------------------------------------
22
+
23
+ var errorMessage = 'Emojis should be wrapped in <span>, have role="img", and have an accessible description with aria-label or aria-labelledby.';
24
+ var schema = (0, _schemas.generateObjSchema)();
25
+ var _default = exports["default"] = {
26
+ meta: {
27
+ docs: {
28
+ description: 'Enforce emojis are wrapped in `<span>` and provide screen reader access.',
29
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/accessible-emoji.md'
30
+ },
31
+ deprecated: true,
32
+ schema: [schema]
33
+ },
34
+ create: function create(context) {
35
+ var elementType = (0, _getElementType["default"])(context);
36
+ var testEmoji = (0, _safeRegexTest["default"])((0, _emojiRegex["default"])());
37
+ return {
38
+ JSXOpeningElement: function JSXOpeningElement(node) {
39
+ var literalChildValue = node.parent.children.find(function (child) {
40
+ return child.type === 'Literal' || child.type === 'JSXText';
41
+ });
42
+ if (literalChildValue && testEmoji(literalChildValue.value)) {
43
+ var elementIsHidden = (0, _isHiddenFromScreenReader["default"])(elementType(node), node.attributes);
44
+ if (elementIsHidden) {
45
+ return; // emoji is decorative
46
+ }
47
+ var rolePropValue = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'role'));
48
+ var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
49
+ var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
50
+ var hasLabel = ariaLabelProp !== undefined || arialLabelledByProp !== undefined;
51
+ var isSpan = elementType(node) === 'span';
52
+ if (hasLabel === false || rolePropValue !== 'img' || isSpan === false) {
53
+ context.report({
54
+ node,
55
+ message: errorMessage
56
+ });
57
+ }
58
+ }
59
+ }
60
+ };
61
+ }
62
+ };
63
+ module.exports = exports.default;
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _jsxAstUtils = require("jsx-ast-utils");
8
+ var _arrayPrototype = _interopRequireDefault(require("array.prototype.flatmap"));
9
+ var _schemas = require("../util/schemas");
10
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
11
+ var _hasAccessibleChild = _interopRequireDefault(require("../util/hasAccessibleChild"));
12
+ var _isPresentationRole = _interopRequireDefault(require("../util/isPresentationRole"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
14
+ /**
15
+ * @fileoverview Enforce all elements that require alternative text have it.
16
+ * @author Ethan Cohen
17
+ */
18
+
19
+ // ----------------------------------------------------------------------------
20
+ // Rule Definition
21
+ // ----------------------------------------------------------------------------
22
+
23
+ var DEFAULT_ELEMENTS = ['img', 'object', 'area', 'input[type="image"]'];
24
+ var schema = (0, _schemas.generateObjSchema)({
25
+ elements: _schemas.arraySchema,
26
+ img: _schemas.arraySchema,
27
+ object: _schemas.arraySchema,
28
+ area: _schemas.arraySchema,
29
+ 'input[type="image"]': _schemas.arraySchema
30
+ });
31
+ var ariaLabelHasValue = function ariaLabelHasValue(prop) {
32
+ var value = (0, _jsxAstUtils.getPropValue)(prop);
33
+ if (value === undefined) {
34
+ return false;
35
+ }
36
+ if (typeof value === 'string' && value.length === 0) {
37
+ return false;
38
+ }
39
+ return true;
40
+ };
41
+ var ruleByElement = {
42
+ img(context, node, nodeType) {
43
+ var altProp = (0, _jsxAstUtils.getProp)(node.attributes, 'alt');
44
+
45
+ // Missing alt prop error.
46
+ if (altProp === undefined) {
47
+ if ((0, _isPresentationRole["default"])(nodeType, node.attributes)) {
48
+ context.report({
49
+ node,
50
+ message: 'Prefer alt="" over a presentational role. First rule of aria is to not use aria if it can be achieved via native HTML.'
51
+ });
52
+ return;
53
+ }
54
+ // Check for `aria-label` to provide text alternative
55
+ // Don't create an error if the attribute is used correctly. But if it
56
+ // isn't, suggest that the developer use `alt` instead.
57
+ var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
58
+ if (ariaLabelProp !== undefined) {
59
+ if (!ariaLabelHasValue(ariaLabelProp)) {
60
+ context.report({
61
+ node,
62
+ message: 'The aria-label attribute must have a value. The alt attribute is preferred over aria-label for images.'
63
+ });
64
+ }
65
+ return;
66
+ }
67
+ // Check for `aria-labelledby` to provide text alternative
68
+ // Don't create an error if the attribute is used correctly. But if it
69
+ // isn't, suggest that the developer use `alt` instead.
70
+ var ariaLabelledbyProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
71
+ if (ariaLabelledbyProp !== undefined) {
72
+ if (!ariaLabelHasValue(ariaLabelledbyProp)) {
73
+ context.report({
74
+ node,
75
+ message: 'The aria-labelledby attribute must have a value. The alt attribute is preferred over aria-labelledby for images.'
76
+ });
77
+ }
78
+ return;
79
+ }
80
+ context.report({
81
+ node,
82
+ message: "".concat(nodeType, " elements must have an alt prop, either with meaningful text, or an empty string for decorative images.")
83
+ });
84
+ return;
85
+ }
86
+
87
+ // Check if alt prop is undefined.
88
+ var altValue = (0, _jsxAstUtils.getPropValue)(altProp);
89
+ var isNullValued = altProp.value === null; // <img alt />
90
+
91
+ if (altValue && !isNullValued || altValue === '') {
92
+ return;
93
+ }
94
+
95
+ // Undefined alt prop error.
96
+ context.report({
97
+ node,
98
+ message: "Invalid alt value for ".concat(nodeType, ". Use alt=\"\" for presentational images.")
99
+ });
100
+ },
101
+ object(context, node, unusedNodeType, elementType) {
102
+ var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
103
+ var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
104
+ var hasLabel = ariaLabelHasValue(ariaLabelProp) || ariaLabelHasValue(arialLabelledByProp);
105
+ var titleProp = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'title'));
106
+ var hasTitleAttr = !!titleProp;
107
+ if (hasLabel || hasTitleAttr || (0, _hasAccessibleChild["default"])(node.parent, elementType)) {
108
+ return;
109
+ }
110
+ context.report({
111
+ node,
112
+ message: 'Embedded <object> elements must have alternative text by providing inner text, aria-label or aria-labelledby props.'
113
+ });
114
+ },
115
+ area(context, node) {
116
+ var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
117
+ var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
118
+ var hasLabel = ariaLabelHasValue(ariaLabelProp) || ariaLabelHasValue(arialLabelledByProp);
119
+ if (hasLabel) {
120
+ return;
121
+ }
122
+ var altProp = (0, _jsxAstUtils.getProp)(node.attributes, 'alt');
123
+ if (altProp === undefined) {
124
+ context.report({
125
+ node,
126
+ message: 'Each area of an image map must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
127
+ });
128
+ return;
129
+ }
130
+ var altValue = (0, _jsxAstUtils.getPropValue)(altProp);
131
+ var isNullValued = altProp.value === null; // <area alt />
132
+
133
+ if (altValue && !isNullValued || altValue === '') {
134
+ return;
135
+ }
136
+ context.report({
137
+ node,
138
+ message: 'Each area of an image map must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
139
+ });
140
+ },
141
+ 'input[type="image"]': function inputImage(context, node, nodeType) {
142
+ // Only test input[type="image"]
143
+ if (nodeType === 'input') {
144
+ var typePropValue = (0, _jsxAstUtils.getPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'type'));
145
+ if (typePropValue !== 'image') {
146
+ return;
147
+ }
148
+ }
149
+ var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
150
+ var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
151
+ var hasLabel = ariaLabelHasValue(ariaLabelProp) || ariaLabelHasValue(arialLabelledByProp);
152
+ if (hasLabel) {
153
+ return;
154
+ }
155
+ var altProp = (0, _jsxAstUtils.getProp)(node.attributes, 'alt');
156
+ if (altProp === undefined) {
157
+ context.report({
158
+ node,
159
+ message: '<input> elements with type="image" must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
160
+ });
161
+ return;
162
+ }
163
+ var altValue = (0, _jsxAstUtils.getPropValue)(altProp);
164
+ var isNullValued = altProp.value === null; // <area alt />
165
+
166
+ if (altValue && !isNullValued || altValue === '') {
167
+ return;
168
+ }
169
+ context.report({
170
+ node,
171
+ message: '<input> elements with type="image" must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
172
+ });
173
+ }
174
+ };
175
+ var _default = exports["default"] = {
176
+ meta: {
177
+ docs: {
178
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/alt-text.md',
179
+ description: 'Enforce all elements that require alternative text have meaningful information to relay back to end user.'
180
+ },
181
+ schema: [schema]
182
+ },
183
+ create: function create(context) {
184
+ var options = context.options[0] || {};
185
+ // Elements to validate for alt text.
186
+ var elementOptions = options.elements || DEFAULT_ELEMENTS;
187
+ // Get custom components for just the elements that will be tested.
188
+ var customComponents = (0, _arrayPrototype["default"])(elementOptions, function (element) {
189
+ return options[element];
190
+ });
191
+ var typesToValidate = new Set([].concat(customComponents, elementOptions).map(function (type) {
192
+ return type === 'input[type="image"]' ? 'input' : type;
193
+ }));
194
+ var elementType = (0, _getElementType["default"])(context);
195
+ return {
196
+ JSXOpeningElement(node) {
197
+ var nodeType = elementType(node);
198
+ if (!typesToValidate.has(nodeType)) {
199
+ return;
200
+ }
201
+ var DOMElement = nodeType;
202
+ if (DOMElement === 'input') {
203
+ DOMElement = 'input[type="image"]';
204
+ }
205
+
206
+ // Map nodeType to the DOM element if we are running this on a custom component.
207
+ if (elementOptions.indexOf(DOMElement) === -1) {
208
+ DOMElement = elementOptions.find(function (element) {
209
+ var customComponentsForElement = options[element] || [];
210
+ return customComponentsForElement.indexOf(nodeType) > -1;
211
+ });
212
+ }
213
+ ruleByElement[DOMElement](context, node, nodeType, elementType);
214
+ }
215
+ };
216
+ }
217
+ };
218
+ module.exports = exports.default;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _schemas = require("../util/schemas");
8
+ var _getAccessibleChildText = _interopRequireDefault(require("../util/getAccessibleChildText"));
9
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
11
+ /**
12
+ * @fileoverview Enforce anchor text to not exactly match 'click here', 'here', 'link', 'learn more', and user-specified words.
13
+ * @author Matt Wang
14
+ *
15
+ */
16
+
17
+ // ----------------------------------------------------------------------------
18
+ // Rule Definition
19
+ // ----------------------------------------------------------------------------
20
+
21
+ var DEFAULT_AMBIGUOUS_WORDS = ['click here', 'here', 'link', 'a link', 'learn more'];
22
+ var schema = (0, _schemas.generateObjSchema)({
23
+ words: _schemas.arraySchema
24
+ });
25
+ var _default = exports["default"] = {
26
+ meta: {
27
+ docs: {
28
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/anchor-ambiguous-text.md',
29
+ description: 'Enforce `<a>` text to not exactly match "click here", "here", "link", or "a link".'
30
+ },
31
+ schema: [schema]
32
+ },
33
+ create: function create(context) {
34
+ var elementType = (0, _getElementType["default"])(context);
35
+ var typesToValidate = ['a'];
36
+ var options = context.options[0] || {};
37
+ var _options$words = options.words,
38
+ words = _options$words === void 0 ? DEFAULT_AMBIGUOUS_WORDS : _options$words;
39
+ var ambiguousWords = new Set(words);
40
+ return {
41
+ JSXOpeningElement: function JSXOpeningElement(node) {
42
+ var nodeType = elementType(node);
43
+
44
+ // Only check anchor elements and custom types.
45
+ if (typesToValidate.indexOf(nodeType) === -1) {
46
+ return;
47
+ }
48
+ var nodeText = (0, _getAccessibleChildText["default"])(node.parent, elementType);
49
+ if (!ambiguousWords.has(nodeText)) {
50
+ // check the value
51
+ return;
52
+ }
53
+ context.report({
54
+ node,
55
+ message: 'Ambiguous text within anchor. Screen reader users rely on link text for context; the words "{{wordsList}}" are ambiguous and do not provide enough context.',
56
+ data: {
57
+ wordsList: words.join('", "')
58
+ }
59
+ });
60
+ }
61
+ };
62
+ }
63
+ };
64
+ module.exports = exports.default;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _jsxAstUtils = require("jsx-ast-utils");
8
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
9
+ var _schemas = require("../util/schemas");
10
+ var _hasAccessibleChild = _interopRequireDefault(require("../util/hasAccessibleChild"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
12
+ /**
13
+ * @fileoverview Enforce anchor elements to contain accessible content.
14
+ * @author Lisa Ring & Niklas Holmberg
15
+ */
16
+
17
+ // ----------------------------------------------------------------------------
18
+ // Rule Definition
19
+ // ----------------------------------------------------------------------------
20
+
21
+ var errorMessage = 'Anchors must have content and the content must be accessible by a screen reader.';
22
+ var schema = (0, _schemas.generateObjSchema)({
23
+ components: _schemas.arraySchema
24
+ });
25
+ var _default = exports["default"] = {
26
+ meta: {
27
+ docs: {
28
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/anchor-has-content.md',
29
+ description: 'Enforce all anchors to contain accessible content.'
30
+ },
31
+ schema: [schema]
32
+ },
33
+ create: function create(context) {
34
+ var elementType = (0, _getElementType["default"])(context);
35
+ return {
36
+ JSXOpeningElement: function JSXOpeningElement(node) {
37
+ var options = context.options[0] || {};
38
+ var componentOptions = options.components || [];
39
+ var typeCheck = ['a'].concat(componentOptions);
40
+ var nodeType = elementType(node);
41
+
42
+ // Only check anchor elements and custom types.
43
+ if (typeCheck.indexOf(nodeType) === -1) {
44
+ return;
45
+ }
46
+ if ((0, _hasAccessibleChild["default"])(node.parent, elementType)) {
47
+ return;
48
+ }
49
+ if ((0, _jsxAstUtils.hasAnyProp)(node.attributes, ['title', 'aria-label'])) {
50
+ return;
51
+ }
52
+ context.report({
53
+ node,
54
+ message: errorMessage
55
+ });
56
+ }
57
+ };
58
+ }
59
+ };
60
+ module.exports = exports.default;