@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,75 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _ariaQuery = require("aria-query");
8
+ var _jsxAstUtils = require("jsx-ast-utils");
9
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
10
+ var _schemas = require("../util/schemas");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
12
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
13
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
14
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
15
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
16
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
17
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
18
+ var errorMessage = 'Use {{tag}} instead of the "{{role}}" role to ensure accessibility across all devices.';
19
+ var schema = (0, _schemas.generateObjSchema)();
20
+ var formatTag = function formatTag(tag) {
21
+ if (!tag.attributes) {
22
+ return "<".concat(tag.name, ">");
23
+ }
24
+ var _tag$attributes = _slicedToArray(tag.attributes, 1),
25
+ attribute = _tag$attributes[0];
26
+ var value = attribute.value ? "\"".concat(attribute.value, "\"") : '...';
27
+ return "<".concat(tag.name, " ").concat(attribute.name, "=").concat(value, ">");
28
+ };
29
+ var getLastPropValue = function getLastPropValue(rawProp) {
30
+ var propValue = (0, _jsxAstUtils.getPropValue)(rawProp);
31
+ if (!propValue) {
32
+ return propValue;
33
+ }
34
+ var lastSpaceIndex = propValue.lastIndexOf(' ');
35
+ return lastSpaceIndex === -1 ? propValue : propValue.substring(lastSpaceIndex + 1);
36
+ };
37
+ var _default = exports["default"] = {
38
+ meta: {
39
+ docs: {
40
+ description: 'Enforces using semantic DOM elements over the ARIA `role` property.',
41
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/prefer-tag-over-role.md'
42
+ },
43
+ schema: [schema]
44
+ },
45
+ create: function create(context) {
46
+ var elementType = (0, _getElementType["default"])(context);
47
+ return {
48
+ JSXOpeningElement: function JSXOpeningElement(node) {
49
+ var role = getLastPropValue((0, _jsxAstUtils.getProp)(node.attributes, 'role'));
50
+ if (!role) {
51
+ return;
52
+ }
53
+ var matchedTagsSet = _ariaQuery.roleElements.get(role);
54
+ if (!matchedTagsSet) {
55
+ return;
56
+ }
57
+ var matchedTags = Array.from(matchedTagsSet);
58
+ if (matchedTags.some(function (matchedTag) {
59
+ return matchedTag.name === elementType(node);
60
+ })) {
61
+ return;
62
+ }
63
+ context.report({
64
+ data: {
65
+ tag: matchedTags.length === 1 ? formatTag(matchedTags[0]) : [matchedTags.slice(0, matchedTags.length - 1).map(formatTag).join(', '), formatTag(matchedTags[matchedTags.length - 1])].join(', or '),
66
+ role
67
+ },
68
+ node,
69
+ message: errorMessage
70
+ });
71
+ }
72
+ };
73
+ }
74
+ };
75
+ module.exports = exports.default;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _ariaQuery = require("aria-query");
8
+ var _jsxAstUtils = require("jsx-ast-utils");
9
+ var _schemas = require("../util/schemas");
10
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
11
+ var _isSemanticRoleElement = _interopRequireDefault(require("../util/isSemanticRoleElement"));
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
13
+ /**
14
+ * @fileoverview Enforce that elements with ARIA roles must
15
+ * have all required attributes for that role.
16
+ * @author Ethan Cohen
17
+ */
18
+
19
+ // ----------------------------------------------------------------------------
20
+ // Rule Definition
21
+ // ----------------------------------------------------------------------------
22
+
23
+ var errorMessage = function errorMessage(role, requiredProps) {
24
+ return "Elements with the ARIA role \"".concat(role, "\" must have the following attributes defined: ").concat(String(requiredProps).toLowerCase());
25
+ };
26
+ var schema = (0, _schemas.generateObjSchema)();
27
+ var roleKeys = _ariaQuery.roles.keys();
28
+ var _default = exports["default"] = {
29
+ meta: {
30
+ docs: {
31
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/role-has-required-aria-props.md',
32
+ description: 'Enforce that elements with ARIA roles must have all required attributes for that role.'
33
+ },
34
+ schema: [schema]
35
+ },
36
+ create: function create(context) {
37
+ var elementType = (0, _getElementType["default"])(context);
38
+ return {
39
+ JSXAttribute: function JSXAttribute(attribute) {
40
+ var name = (0, _jsxAstUtils.propName)(attribute).toLowerCase();
41
+ if (name !== 'role') {
42
+ return;
43
+ }
44
+ var type = elementType(attribute.parent);
45
+ if (!_ariaQuery.dom.get(type)) {
46
+ return;
47
+ }
48
+ var roleAttrValue = (0, _jsxAstUtils.getLiteralPropValue)(attribute);
49
+ var attributes = attribute.parent.attributes;
50
+
51
+ // If value is undefined, then the role attribute will be dropped in the DOM.
52
+ // If value is null, then getLiteralAttributeValue is telling us
53
+ // that the value isn't in the form of a literal.
54
+ if (roleAttrValue === undefined || roleAttrValue === null) {
55
+ return;
56
+ }
57
+ var normalizedValues = String(roleAttrValue).toLowerCase().split(' ');
58
+ var validRoles = normalizedValues.filter(function (val) {
59
+ return roleKeys.indexOf(val) > -1;
60
+ });
61
+
62
+ // Check semantic DOM elements
63
+ // For example, <input type="checkbox" role="switch" />
64
+ if ((0, _isSemanticRoleElement["default"])(type, attributes)) {
65
+ return;
66
+ }
67
+ // Check arbitrary DOM elements
68
+ validRoles.forEach(function (role) {
69
+ var _roles$get = _ariaQuery.roles.get(role),
70
+ requiredPropKeyValues = _roles$get.requiredProps;
71
+ var requiredProps = Object.keys(requiredPropKeyValues);
72
+ if (requiredProps.length > 0) {
73
+ var hasRequiredProps = requiredProps.every(function (prop) {
74
+ return (0, _jsxAstUtils.getProp)(attributes, prop);
75
+ });
76
+ if (hasRequiredProps === false) {
77
+ context.report({
78
+ node: attribute,
79
+ message: errorMessage(role.toLowerCase(), requiredProps)
80
+ });
81
+ }
82
+ }
83
+ });
84
+ }
85
+ };
86
+ }
87
+ };
88
+ module.exports = exports.default;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _ariaQuery = require("aria-query");
8
+ var _jsxAstUtils = require("jsx-ast-utils");
9
+ var _schemas = require("../util/schemas");
10
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
11
+ var _getImplicitRole = _interopRequireDefault(require("../util/getImplicitRole"));
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
13
+ /**
14
+ * @fileoverview Enforce that elements with explicit or implicit roles defined contain only
15
+ * `aria-*` properties supported by that `role`.
16
+ * @author Ethan Cohen
17
+ */
18
+
19
+ // ----------------------------------------------------------------------------
20
+ // Rule Definition
21
+ // ----------------------------------------------------------------------------
22
+
23
+ var errorMessage = function errorMessage(attr, role, tag, isImplicit) {
24
+ if (isImplicit) {
25
+ return "The attribute ".concat(attr, " is not supported by the role ").concat(role, ". This role is implicit on the element ").concat(tag, ".");
26
+ }
27
+ return "The attribute ".concat(attr, " is not supported by the role ").concat(role, ".");
28
+ };
29
+ var schema = (0, _schemas.generateObjSchema)();
30
+ var _default = exports["default"] = {
31
+ meta: {
32
+ docs: {
33
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/role-supports-aria-props.md',
34
+ description: 'Enforce that elements with explicit or implicit roles defined contain only `aria-*` properties supported by that `role`.'
35
+ },
36
+ schema: [schema]
37
+ },
38
+ create(context) {
39
+ var elementType = (0, _getElementType["default"])(context);
40
+ return {
41
+ JSXOpeningElement(node) {
42
+ // If role is not explicitly defined, then try and get its implicit role.
43
+ var type = elementType(node);
44
+ var role = (0, _jsxAstUtils.getProp)(node.attributes, 'role');
45
+ var roleValue = role ? (0, _jsxAstUtils.getLiteralPropValue)(role) : (0, _getImplicitRole["default"])(type, node.attributes);
46
+ var isImplicit = roleValue && role === undefined;
47
+
48
+ // If there is no explicit or implicit role, then assume that the element
49
+ // can handle the global set of aria-* properties.
50
+ // This actually isn't true - should fix in future release.
51
+ if (typeof roleValue !== 'string' || _ariaQuery.roles.get(roleValue) === undefined) {
52
+ return;
53
+ }
54
+
55
+ // Make sure it has no aria-* properties defined outside its property set.
56
+ var _roles$get = _ariaQuery.roles.get(roleValue),
57
+ propKeyValues = _roles$get.props;
58
+ var invalidAriaPropsForRole = new Set(_ariaQuery.aria.keys().filter(function (attribute) {
59
+ return !(attribute in propKeyValues);
60
+ }));
61
+ node.attributes.filter(function (prop) {
62
+ return (0, _jsxAstUtils.getPropValue)(prop) != null // Ignore the attribute if its value is null or undefined.
63
+ && prop.type !== 'JSXSpreadAttribute' // Ignore the attribute if it's a spread.
64
+ ;
65
+ }).forEach(function (prop) {
66
+ var name = (0, _jsxAstUtils.propName)(prop);
67
+ if (invalidAriaPropsForRole.has(name)) {
68
+ context.report({
69
+ node,
70
+ message: errorMessage(name, roleValue, type, isImplicit)
71
+ });
72
+ }
73
+ });
74
+ }
75
+ };
76
+ }
77
+ };
78
+ module.exports = exports.default;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _ariaQuery = require("aria-query");
8
+ var _jsxAstUtils = require("jsx-ast-utils");
9
+ var _schemas = require("../util/schemas");
10
+ var _getElementType = _interopRequireDefault(require("../util/getElementType"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
12
+ /**
13
+ * @fileoverview Enforce scope prop is only used on <th> elements.
14
+ * @author Ethan Cohen
15
+ */
16
+
17
+ // ----------------------------------------------------------------------------
18
+ // Rule Definition
19
+ // ----------------------------------------------------------------------------
20
+
21
+ var errorMessage = 'The scope prop can only be used on <th> elements.';
22
+ var schema = (0, _schemas.generateObjSchema)();
23
+ var _default = exports["default"] = {
24
+ meta: {
25
+ docs: {
26
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/scope.md',
27
+ description: 'Enforce `scope` prop is only used on `<th>` elements.'
28
+ },
29
+ schema: [schema]
30
+ },
31
+ create: function create(context) {
32
+ var elementType = (0, _getElementType["default"])(context);
33
+ return {
34
+ JSXAttribute: function JSXAttribute(node) {
35
+ var name = (0, _jsxAstUtils.propName)(node);
36
+ if (name && name.toUpperCase() !== 'SCOPE') {
37
+ return;
38
+ }
39
+ var parent = node.parent;
40
+ var tagName = elementType(parent);
41
+
42
+ // Do not test higher level JSX components, as we do not know what
43
+ // low-level DOM element this maps to.
44
+ if (!_ariaQuery.dom.has(tagName)) {
45
+ return;
46
+ }
47
+ if (tagName && tagName.toUpperCase() === 'TH') {
48
+ return;
49
+ }
50
+ context.report({
51
+ node,
52
+ message: errorMessage
53
+ });
54
+ }
55
+ };
56
+ }
57
+ };
58
+ module.exports = exports.default;
@@ -0,0 +1,53 @@
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 _schemas = require("../util/schemas");
9
+ /**
10
+ * @fileoverview Enforce tabIndex value is not greater than zero.
11
+ * @author Ethan Cohen
12
+ */
13
+
14
+ // ----------------------------------------------------------------------------
15
+ // Rule Definition
16
+ // ----------------------------------------------------------------------------
17
+
18
+ var errorMessage = 'Avoid positive integer values for tabIndex.';
19
+ var schema = (0, _schemas.generateObjSchema)();
20
+ var _default = exports["default"] = {
21
+ meta: {
22
+ docs: {
23
+ url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/tabindex-no-positive.md',
24
+ description: 'Enforce `tabIndex` value is not greater than zero.'
25
+ },
26
+ schema: [schema]
27
+ },
28
+ create: function create(context) {
29
+ return {
30
+ JSXAttribute: function JSXAttribute(attribute) {
31
+ var name = (0, _jsxAstUtils.propName)(attribute).toUpperCase();
32
+
33
+ // Check if tabIndex is the attribute
34
+ if (name !== 'TABINDEX') {
35
+ return;
36
+ }
37
+
38
+ // Only check literals because we can't infer values from certain expressions.
39
+ var value = Number((0, _jsxAstUtils.getLiteralPropValue)(attribute));
40
+
41
+ // eslint-disable-next-line no-restricted-globals
42
+ if (isNaN(value) || value <= 0) {
43
+ return;
44
+ }
45
+ context.report({
46
+ node: attribute,
47
+ message: errorMessage
48
+ });
49
+ }
50
+ };
51
+ }
52
+ };
53
+ module.exports = exports.default;
@@ -0,0 +1,34 @@
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
+ /**
9
+ * Returns true if all items in baseAttributes are found in attributes. Always
10
+ * returns true if baseAttributes is empty.
11
+ */
12
+ function attributesComparator() {
13
+ var baseAttributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
14
+ var attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
15
+ return baseAttributes.every(function (baseAttr) {
16
+ return attributes.some(function (attribute) {
17
+ // Guard against non-JSXAttribute nodes like JSXSpreadAttribute
18
+ if (attribute.type !== 'JSXAttribute') {
19
+ return false;
20
+ }
21
+ // Attribute matches.
22
+ if (baseAttr.name !== (0, _jsxAstUtils.propName)(attribute)) {
23
+ return false;
24
+ }
25
+ // Value exists and does not match.
26
+ if (baseAttr.value && baseAttr.value !== (0, _jsxAstUtils.getLiteralPropValue)(attribute)) {
27
+ return false;
28
+ }
29
+ return true;
30
+ });
31
+ });
32
+ }
33
+ var _default = exports["default"] = attributesComparator;
34
+ module.exports = exports.default;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = getAccessibleChildText;
7
+ var _jsxAstUtils = require("jsx-ast-utils");
8
+ var _isHiddenFromScreenReader = _interopRequireDefault(require("./isHiddenFromScreenReader"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
10
+ /**
11
+ * Returns a new "standardized" string: all whitespace is collapsed to one space,
12
+ * and the string is lowercase
13
+ * @param {string} input
14
+ * @returns lowercase, single-spaced, punctuation-stripped, trimmed string
15
+ */
16
+ function standardizeSpaceAndCase(input) {
17
+ return input.trim().replace(/[,.?¿!‽¡;:]/g, '') // strip punctuation
18
+ .replace(/\s\s+/g, ' ') // collapse spaces
19
+ .toLowerCase();
20
+ }
21
+
22
+ /**
23
+ * Returns the (recursively-defined) accessible child text of a node, which (in-order) is:
24
+ * 1. The element's aria-label
25
+ * 2. If the element is a direct literal, the literal value
26
+ * 3. Otherwise, merge all of its children
27
+ * @param {JSXElement} node - node to traverse
28
+ * @returns child text as a string
29
+ */
30
+ function getAccessibleChildText(node, elementType) {
31
+ var ariaLabel = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.openingElement.attributes, 'aria-label'));
32
+ // early escape-hatch when aria-label is applied
33
+ if (ariaLabel) return standardizeSpaceAndCase(ariaLabel);
34
+
35
+ // early-return if alt prop exists and is an image
36
+ var altTag = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.openingElement.attributes, 'alt'));
37
+ if (elementType(node.openingElement) === 'img' && altTag) return standardizeSpaceAndCase(altTag);
38
+
39
+ // skip if aria-hidden is true
40
+ if ((0, _isHiddenFromScreenReader["default"])(elementType(node.openingElement), node.openingElement.attributes)) {
41
+ return '';
42
+ }
43
+ var rawChildText = node.children.map(function (currentNode) {
44
+ // $FlowFixMe JSXText is missing in ast-types-flow
45
+ if (currentNode.type === 'Literal' || currentNode.type === 'JSXText') {
46
+ return String(currentNode.value);
47
+ }
48
+ if (currentNode.type === 'JSXElement') {
49
+ return getAccessibleChildText(currentNode, elementType);
50
+ }
51
+ return '';
52
+ }).join(' ');
53
+ return standardizeSpaceAndCase(rawChildText);
54
+ }
55
+ module.exports = exports.default;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = getComputedRole;
7
+ var _getExplicitRole = _interopRequireDefault(require("./getExplicitRole"));
8
+ var _getImplicitRole = _interopRequireDefault(require("./getImplicitRole"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
10
+ /**
11
+ * Returns an element's computed role, which is
12
+ *
13
+ * 1. The valid value of its explicit role attribute; or
14
+ * 2. The implicit value of its tag.
15
+ */
16
+ function getComputedRole(tag, attributes) {
17
+ return (0, _getExplicitRole["default"])(tag, attributes) || (0, _getImplicitRole["default"])(tag, attributes);
18
+ }
19
+ module.exports = exports.default;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _hasown = _interopRequireDefault(require("hasown"));
8
+ var _arrayIncludes = _interopRequireDefault(require("array-includes"));
9
+ var _jsxAstUtils = require("jsx-ast-utils");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
11
+ var getElementType = function getElementType(context) {
12
+ var _settings$jsxA11y, _settings$jsxA11y2, _settings$jsxA11y3;
13
+ var settings = context.settings;
14
+ var polymorphicPropName = (_settings$jsxA11y = settings['jsx-a11y']) === null || _settings$jsxA11y === void 0 ? void 0 : _settings$jsxA11y.polymorphicPropName;
15
+ var polymorphicAllowList = (_settings$jsxA11y2 = settings['jsx-a11y']) === null || _settings$jsxA11y2 === void 0 ? void 0 : _settings$jsxA11y2.polymorphicAllowList;
16
+ var componentMap = (_settings$jsxA11y3 = settings['jsx-a11y']) === null || _settings$jsxA11y3 === void 0 ? void 0 : _settings$jsxA11y3.components;
17
+ return function (node) {
18
+ var polymorphicProp = polymorphicPropName ? (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.attributes, polymorphicPropName)) : undefined;
19
+ var rawType = (0, _jsxAstUtils.elementType)(node);
20
+ if (polymorphicProp && (!polymorphicAllowList || (0, _arrayIncludes["default"])(polymorphicAllowList, rawType))) {
21
+ rawType = polymorphicProp;
22
+ }
23
+ if (!componentMap) {
24
+ return rawType;
25
+ }
26
+ return (0, _hasown["default"])(componentMap, rawType) ? componentMap[rawType] : rawType;
27
+ };
28
+ };
29
+ var _default = exports["default"] = getElementType;
30
+ module.exports = exports.default;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = getExplicitRole;
7
+ var _ariaQuery = require("aria-query");
8
+ var _jsxAstUtils = require("jsx-ast-utils");
9
+ /**
10
+ * Returns an element's computed role, which is
11
+ *
12
+ * 1. The valid value of its explicit role attribute; or
13
+ * 2. The implicit value of its tag.
14
+ */
15
+ function getExplicitRole(tag, attributes) {
16
+ var explicitRole = function toLowerCase(role) {
17
+ if (typeof role === 'string') {
18
+ return role.toLowerCase();
19
+ }
20
+ return null;
21
+ }((0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(attributes, 'role')));
22
+ if (_ariaQuery.roles.has(explicitRole)) {
23
+ return explicitRole;
24
+ }
25
+ return null;
26
+ }
27
+ module.exports = exports.default;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = getImplicitRole;
7
+ var _ariaQuery = require("aria-query");
8
+ var _implicitRoles = _interopRequireDefault(require("./implicitRoles"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
10
+ /**
11
+ * Returns an element's implicit role given its attributes and type.
12
+ * Some elements only have an implicit role when certain props are defined.
13
+ */
14
+ function getImplicitRole(type, attributes) {
15
+ var implicitRole;
16
+ if (_implicitRoles["default"][type]) {
17
+ implicitRole = _implicitRoles["default"][type](attributes);
18
+ }
19
+ if (_ariaQuery.roles.has(implicitRole)) {
20
+ return implicitRole;
21
+ }
22
+ return null;
23
+ }
24
+ module.exports = exports.default;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = getSuggestion;
7
+ var _damerauLevenshtein = _interopRequireDefault(require("damerau-levenshtein"));
8
+ var _object = _interopRequireDefault(require("object.fromentries"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
10
+ // Minimum edit distance to be considered a good suggestion.
11
+ var THRESHOLD = 2;
12
+
13
+ /**
14
+ * Returns an array of suggestions given a word and a dictionary and limit of suggestions
15
+ * to return.
16
+ */
17
+ function getSuggestion(word) {
18
+ var dictionary = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
19
+ var limit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 2;
20
+ var distances = (0, _object["default"])(dictionary.map(function (dictionaryWord) {
21
+ var distance = (0, _damerauLevenshtein["default"])(word.toUpperCase(), dictionaryWord.toUpperCase());
22
+ var steps = distance.steps;
23
+ return [dictionaryWord, steps];
24
+ }));
25
+ return Object.keys(distances).filter(function (suggestion) {
26
+ return distances[suggestion] <= THRESHOLD;
27
+ }).sort(function (a, b) {
28
+ return distances[a] - distances[b];
29
+ }) // Sort by distance
30
+ .slice(0, limit);
31
+ }
32
+ module.exports = exports.default;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = getTabIndex;
7
+ var _jsxAstUtils = require("jsx-ast-utils");
8
+ 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); }
9
+ /**
10
+ * Returns the tabIndex value.
11
+ */
12
+ function getTabIndex(tabIndex) {
13
+ var literalValue = (0, _jsxAstUtils.getLiteralPropValue)(tabIndex);
14
+
15
+ // String and number values.
16
+ if (['string', 'number'].indexOf(_typeof(literalValue)) > -1) {
17
+ // Empty string will convert to zero, so check for it explicity.
18
+ if (typeof literalValue === 'string' && literalValue.length === 0) {
19
+ return undefined;
20
+ }
21
+ var value = Number(literalValue);
22
+ if (Number.isNaN(value)) {
23
+ return undefined;
24
+ }
25
+ return Number.isInteger(value) ? value : undefined;
26
+ }
27
+
28
+ // Booleans are not valid values, return undefined.
29
+ if (literalValue === true || literalValue === false) {
30
+ return undefined;
31
+ }
32
+ return (0, _jsxAstUtils.getPropValue)(tabIndex);
33
+ }
34
+ module.exports = exports.default;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = hasAccessibleChild;
7
+ var _jsxAstUtils = require("jsx-ast-utils");
8
+ var _isHiddenFromScreenReader = _interopRequireDefault(require("./isHiddenFromScreenReader"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
10
+ function hasAccessibleChild(node, elementType) {
11
+ return node.children.some(function (child) {
12
+ switch (child.type) {
13
+ case 'Literal':
14
+ return !!child.value;
15
+ // $FlowFixMe JSXText is missing in ast-types-flow
16
+ case 'JSXText':
17
+ return !!child.value;
18
+ case 'JSXElement':
19
+ return !(0, _isHiddenFromScreenReader["default"])(elementType(child.openingElement), child.openingElement.attributes);
20
+ case 'JSXExpressionContainer':
21
+ if (child.expression.type === 'Identifier') {
22
+ return child.expression.name !== 'undefined';
23
+ }
24
+ return true;
25
+ default:
26
+ return false;
27
+ }
28
+ }) || (0, _jsxAstUtils.hasAnyProp)(node.openingElement.attributes, ['dangerouslySetInnerHTML', 'children']);
29
+ }
30
+ module.exports = exports.default;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = getImplicitRoleForAnchor;
7
+ var _jsxAstUtils = require("jsx-ast-utils");
8
+ /**
9
+ * Returns the implicit role for an anchor tag.
10
+ */
11
+ function getImplicitRoleForAnchor(attributes) {
12
+ if ((0, _jsxAstUtils.getProp)(attributes, 'href')) {
13
+ return 'link';
14
+ }
15
+ return '';
16
+ }
17
+ module.exports = exports.default;