media-has-caption.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  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. /**
  12. * @fileoverview <audio> and <video> elements must have a <track> for captions.
  13. * @author Ethan Cohen
  14. *
  15. */
  16. // ----------------------------------------------------------------------------
  17. // Rule Definition
  18. // ----------------------------------------------------------------------------
  19. var errorMessage = 'Media elements such as <audio> and <video> must have a <track> for captions.';
  20. var MEDIA_TYPES = ['audio', 'video'];
  21. var schema = (0, _schemas.generateObjSchema)({
  22. audio: _schemas.arraySchema,
  23. video: _schemas.arraySchema,
  24. track: _schemas.arraySchema
  25. });
  26. var isMediaType = function isMediaType(context, type) {
  27. var options = context.options[0] || {};
  28. return MEDIA_TYPES.concat((0, _arrayPrototype["default"])(MEDIA_TYPES, function (mediaType) {
  29. return options[mediaType];
  30. })).some(function (typeToCheck) {
  31. return typeToCheck === type;
  32. });
  33. };
  34. var isTrackType = function isTrackType(context, type) {
  35. var options = context.options[0] || {};
  36. return ['track'].concat(options.track || []).some(function (typeToCheck) {
  37. return typeToCheck === type;
  38. });
  39. };
  40. var _default = exports["default"] = {
  41. meta: {
  42. docs: {
  43. url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/media-has-caption.md',
  44. description: 'Enforces that `<audio>` and `<video>` elements must have a `<track>` for captions.'
  45. },
  46. schema: [schema]
  47. },
  48. create: function create(context) {
  49. var elementType = (0, _getElementType["default"])(context);
  50. return {
  51. JSXElement: function JSXElement(node) {
  52. var element = node.openingElement;
  53. var type = elementType(element);
  54. if (!isMediaType(context, type)) {
  55. return;
  56. }
  57. var mutedProp = (0, _jsxAstUtils.getProp)(element.attributes, 'muted');
  58. var mutedPropVal = (0, _jsxAstUtils.getLiteralPropValue)(mutedProp);
  59. if (mutedPropVal === true) {
  60. return;
  61. }
  62. // $FlowFixMe https://github.com/facebook/flow/issues/1414
  63. var trackChildren = node.children.filter(function (child) {
  64. if (child.type !== 'JSXElement') {
  65. return false;
  66. }
  67. // $FlowFixMe https://github.com/facebook/flow/issues/1414
  68. return isTrackType(context, elementType(child.openingElement));
  69. });
  70. if (trackChildren.length === 0) {
  71. context.report({
  72. node: element,
  73. message: errorMessage
  74. });
  75. return;
  76. }
  77. var hasCaption = trackChildren.some(function (track) {
  78. var kindProp = (0, _jsxAstUtils.getProp)(track.openingElement.attributes, 'kind');
  79. var kindPropValue = (0, _jsxAstUtils.getLiteralPropValue)(kindProp) || '';
  80. return kindPropValue.toLowerCase() === 'captions';
  81. });
  82. if (!hasCaption) {
  83. context.report({
  84. node: element,
  85. message: errorMessage
  86. });
  87. }
  88. }
  89. };
  90. }
  91. };
  92. module.exports = exports.default;