@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
JavaScript
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 };