img-redundant-alt.js 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports["default"] = void 0;
  6. var _jsxAstUtils = require("jsx-ast-utils");
  7. var _arrayIncludes = _interopRequireDefault(require("array-includes"));
  8. var _stringPrototype = _interopRequireDefault(require("string.prototype.includes"));
  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 img alt attribute does not have the word image, picture, or photo.
  16. * @author Ethan Cohen
  17. */
  18. // ----------------------------------------------------------------------------
  19. // Rule Definition
  20. // ----------------------------------------------------------------------------
  21. var REDUNDANT_WORDS = ['image', 'photo', 'picture'];
  22. var errorMessage = 'Redundant alt attribute. Screen-readers already announce `img` tags as an image. You don’t need to use the words `image`, `photo,` or `picture` (or any specified custom words) in the alt prop.';
  23. var schema = (0, _schemas.generateObjSchema)({
  24. components: _schemas.arraySchema,
  25. words: _schemas.arraySchema
  26. });
  27. var isASCII = (0, _safeRegexTest["default"])(/[\x20-\x7F]+/);
  28. function containsRedundantWord(value, redundantWords) {
  29. var lowercaseRedundantWords = redundantWords.map(function (redundantWord) {
  30. return redundantWord.toLowerCase();
  31. });
  32. if (isASCII(value)) {
  33. return value.split(/\s+/).some(function (valueWord) {
  34. return (0, _arrayIncludes["default"])(lowercaseRedundantWords, valueWord.toLowerCase());
  35. });
  36. }
  37. return lowercaseRedundantWords.some(function (redundantWord) {
  38. return (0, _stringPrototype["default"])(value.toLowerCase(), redundantWord);
  39. });
  40. }
  41. var _default = exports["default"] = {
  42. meta: {
  43. docs: {
  44. url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/img-redundant-alt.md',
  45. description: 'Enforce `<img>` alt prop does not contain the word "image", "picture", or "photo".'
  46. },
  47. schema: [schema]
  48. },
  49. create: function create(context) {
  50. var elementType = (0, _getElementType["default"])(context);
  51. return {
  52. JSXOpeningElement: function JSXOpeningElement(node) {
  53. var options = context.options[0] || {};
  54. var componentOptions = options.components || [];
  55. var typesToValidate = ['img'].concat(componentOptions);
  56. var nodeType = elementType(node);
  57. // Only check 'label' elements and custom types.
  58. if (typesToValidate.indexOf(nodeType) === -1) {
  59. return;
  60. }
  61. var altProp = (0, _jsxAstUtils.getProp)(node.attributes, 'alt');
  62. // Return if alt prop is not present.
  63. if (altProp === undefined) {
  64. return;
  65. }
  66. var value = (0, _jsxAstUtils.getLiteralPropValue)(altProp);
  67. var isVisible = (0, _isHiddenFromScreenReader["default"])(nodeType, node.attributes) === false;
  68. var _options$words = options.words,
  69. words = _options$words === void 0 ? [] : _options$words;
  70. var redundantWords = REDUNDANT_WORDS.concat(words);
  71. if (typeof value === 'string' && isVisible) {
  72. var hasRedundancy = containsRedundantWord(value, redundantWords);
  73. if (hasRedundancy === true) {
  74. context.report({
  75. node,
  76. message: errorMessage
  77. });
  78. }
  79. }
  80. }
  81. };
  82. }
  83. };
  84. module.exports = exports.default;