accessible-emoji.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports["default"] = void 0;
  6. var _emojiRegex = _interopRequireDefault(require("emoji-regex"));
  7. var _jsxAstUtils = require("jsx-ast-utils");
  8. var _safeRegexTest = _interopRequireDefault(require("safe-regex-test"));
  9. var _schemas = require("../util/schemas");
  10. var _getElementType = _interopRequireDefault(require("../util/getElementType"));
  11. var _isHiddenFromScreenReader = _interopRequireDefault(require("../util/isHiddenFromScreenReader"));
  12. function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
  13. /**
  14. * @fileoverview Enforce emojis are wrapped in <span> and provide screen reader access.
  15. * @author Ethan Cohen
  16. */
  17. // ----------------------------------------------------------------------------
  18. // Rule Definition
  19. // ----------------------------------------------------------------------------
  20. var errorMessage = 'Emojis should be wrapped in <span>, have role="img", and have an accessible description with aria-label or aria-labelledby.';
  21. var schema = (0, _schemas.generateObjSchema)();
  22. var _default = exports["default"] = {
  23. meta: {
  24. docs: {
  25. description: 'Enforce emojis are wrapped in `<span>` and provide screen reader access.',
  26. url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/accessible-emoji.md'
  27. },
  28. deprecated: true,
  29. schema: [schema]
  30. },
  31. create: function create(context) {
  32. var elementType = (0, _getElementType["default"])(context);
  33. var testEmoji = (0, _safeRegexTest["default"])((0, _emojiRegex["default"])());
  34. return {
  35. JSXOpeningElement: function JSXOpeningElement(node) {
  36. var literalChildValue = node.parent.children.find(function (child) {
  37. return child.type === 'Literal' || child.type === 'JSXText';
  38. });
  39. if (literalChildValue && testEmoji(literalChildValue.value)) {
  40. var elementIsHidden = (0, _isHiddenFromScreenReader["default"])(elementType(node), node.attributes);
  41. if (elementIsHidden) {
  42. return; // emoji is decorative
  43. }
  44. var rolePropValue = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'role'));
  45. var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
  46. var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
  47. var hasLabel = ariaLabelProp !== undefined || arialLabelledByProp !== undefined;
  48. var isSpan = elementType(node) === 'span';
  49. if (hasLabel === false || rolePropValue !== 'img' || isSpan === false) {
  50. context.report({
  51. node,
  52. message: errorMessage
  53. });
  54. }
  55. }
  56. }
  57. };
  58. }
  59. };
  60. module.exports = exports.default;