@jsxtools/eslint-plugin-jsx-a11y
Version:
Static AST checker for accessibility rules on JSX elements for flat ESLint Config.
48 lines (45 loc) • 2.1 kB
JavaScript
const emojiRegex = require('emoji-regex');
const safeRegexTest = require('safe-regex-test');
const jsxAstUtils = require('../util/module/jsx-ast-utils.cjs');
const schemas = require('../util/schemas.cjs');
const getElementType = require('../util/getElementType.cjs');
const isHiddenFromScreenReader = require('../util/isHiddenFromScreenReader.cjs');
const errorMessage = 'Emojis should be wrapped in <span>, have role="img", and have an accessible description with aria-label or aria-labelledby.';
const schema = schemas.generateObjSchema();
const ruleOfAccessibleEmoji = {
meta: {
docs: {
description: "Enforce emojis are wrapped in `<span>` and provide screenreader access.",
url: "https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/accessible-emoji.md"
},
deprecated: true,
schema: [schema]
},
create: (context) => {
const elementType = getElementType(context);
const testEmoji = safeRegexTest.default(emojiRegex.default());
return {
JSXOpeningElement: (node) => {
const literalChildValue = node.parent.children.find((child) => child.type === "Literal" || child.type === "JSXText");
if (literalChildValue && testEmoji(literalChildValue.value)) {
const elementIsHidden = isHiddenFromScreenReader(elementType(node), node.attributes);
if (elementIsHidden) {
return;
}
const rolePropValue = jsxAstUtils.getLiteralPropValue(jsxAstUtils.getProp(node.attributes, "role"));
const ariaLabelProp = jsxAstUtils.getProp(node.attributes, "aria-label");
const arialLabelledByProp = jsxAstUtils.getProp(node.attributes, "aria-labelledby");
const hasLabel = ariaLabelProp !== void 0 || arialLabelledByProp !== void 0;
const isSpan = elementType(node) === "span";
if (hasLabel === false || rolePropValue !== "img" || isSpan === false) {
context.report({
node,
message: errorMessage
});
}
}
}
};
}
};
module.exports = ruleOfAccessibleEmoji;