no-noninteractive-element-to-interactive-role.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  4. var _ariaQuery = require("aria-query");
  5. var _jsxAstUtils = require("jsx-ast-utils");
  6. var _arrayIncludes = _interopRequireDefault(require("array-includes"));
  7. var _has = _interopRequireDefault(require("has"));
  8. var _getExplicitRole = _interopRequireDefault(require("../util/getExplicitRole"));
  9. var _isNonInteractiveElement = _interopRequireDefault(require("../util/isNonInteractiveElement"));
  10. var _isInteractiveRole = _interopRequireDefault(require("../util/isInteractiveRole"));
  11. /**
  12. * @fileoverview Disallow inherently non-interactive elements to be assigned
  13. * interactive roles.
  14. * @author Jesse Beach
  15. *
  16. */
  17. // ----------------------------------------------------------------------------
  18. // Rule Definition
  19. // ----------------------------------------------------------------------------
  20. var errorMessage = 'Non-interactive elements should not be assigned interactive roles.';
  21. var domElements = (0, _toConsumableArray2["default"])(_ariaQuery.dom.keys());
  22. module.exports = {
  23. meta: {
  24. docs: {
  25. url: 'https://github.com/evcohen/eslint-plugin-jsx-a11y/tree/master/docs/rules/no-noninteractive-element-to-interactive-role.md'
  26. },
  27. schema: [{
  28. type: 'object',
  29. additionalProperties: {
  30. type: 'array',
  31. items: {
  32. type: 'string'
  33. },
  34. uniqueItems: true
  35. }
  36. }]
  37. },
  38. create: function create(context) {
  39. var options = context.options;
  40. return {
  41. JSXAttribute: function JSXAttribute(attribute) {
  42. var attributeName = (0, _jsxAstUtils.propName)(attribute); // $FlowFixMe: [TODO] Mark propName as a JSXIdentifier, not a string.
  43. if (attributeName !== 'role') {
  44. return;
  45. }
  46. var node = attribute.parent;
  47. var attributes = node.attributes;
  48. var type = (0, _jsxAstUtils.elementType)(node);
  49. var role = (0, _getExplicitRole["default"])(type, node.attributes);
  50. if (!(0, _arrayIncludes["default"])(domElements, type)) {
  51. // Do not test higher level JSX components, as we do not know what
  52. // low-level DOM element this maps to.
  53. return;
  54. } // Allow overrides from rule configuration for specific elements and
  55. // roles.
  56. var allowedRoles = options[0] || {};
  57. if ((0, _has["default"])(allowedRoles, type) && (0, _arrayIncludes["default"])(allowedRoles[type], role)) {
  58. return;
  59. }
  60. if ((0, _isNonInteractiveElement["default"])(type, attributes) && (0, _isInteractiveRole["default"])(type, attributes)) {
  61. context.report({
  62. node: attribute,
  63. message: errorMessage
  64. });
  65. }
  66. }
  67. };
  68. }
  69. };