UNPKG

@jsxtools/eslint-plugin-jsx-a11y

Version:

Static AST checker for accessibility rules on JSX elements for flat ESLint Config.

72 lines (69 loc) 2.5 kB
import { getProp, getLiteralPropValue } from '../util/module/jsx-ast-utils.js'; import { generateObjSchema, arraySchema } from '../util/schemas.js'; import getElementType from '../util/getElementType.js'; const errorMessage = "Media elements such as <audio> and <video> must have a <track> for captions."; const MEDIA_TYPES = ["audio", "video"]; const schema = generateObjSchema({ audio: arraySchema, video: arraySchema, track: arraySchema }); const isMediaType = (context, type) => { const options = context.options[0] || {}; return MEDIA_TYPES.concat(MEDIA_TYPES.flatMap((mediaType) => options[mediaType])).some((typeToCheck) => typeToCheck === type); }; const isTrackType = (context, type) => { const options = context.options[0] || {}; return ["track"].concat(options.track || []).some((typeToCheck) => typeToCheck === type); }; const ruleOfMediaHasCaption = { meta: { docs: { url: "https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/media-has-caption.md", description: "Enforces that `<audio>` and `<video>` elements must have a `<track>` for captions." }, schema: [schema] }, create: (context) => { const elementType = getElementType(context); return { JSXElement: (node) => { const element = node.openingElement; const type = elementType(element); if (!isMediaType(context, type)) { return; } const mutedProp = getProp(element.attributes, "muted"); const mutedPropVal = getLiteralPropValue(mutedProp); if (mutedPropVal === true) { return; } const trackChildren = node.children.filter((child) => { if (child.type !== "JSXElement") { return false; } return isTrackType(context, elementType(child.openingElement)); }); if (trackChildren.length === 0) { context.report({ node: element, message: errorMessage }); return; } const hasCaption = trackChildren.some((track) => { const kindProp = getProp(track.openingElement.attributes, "kind"); const kindPropValue = getLiteralPropValue(kindProp) || ""; return kindPropValue.toLowerCase() === "captions"; }); if (!hasCaption) { context.report({ node: element, message: errorMessage }); } } }; } }; export { ruleOfMediaHasCaption as default };