source: frontend/node_modules/eslint-plugin-jsx-a11y/lib/rules/alt-text.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 2 weeks ago

Fix frontend appearance

  • Property mode set to 100644
File size: 8.5 KB
RevLine 
[9af201e]1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports["default"] = void 0;
7var _jsxAstUtils = require("jsx-ast-utils");
8var _arrayPrototype = _interopRequireDefault(require("array.prototype.flatmap"));
9var _schemas = require("../util/schemas");
10var _getElementType = _interopRequireDefault(require("../util/getElementType"));
11var _hasAccessibleChild = _interopRequireDefault(require("../util/hasAccessibleChild"));
12var _isPresentationRole = _interopRequireDefault(require("../util/isPresentationRole"));
13function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
14/**
15 * @fileoverview Enforce all elements that require alternative text have it.
16 * @author Ethan Cohen
17 */
18
19// ----------------------------------------------------------------------------
20// Rule Definition
21// ----------------------------------------------------------------------------
22
23var DEFAULT_ELEMENTS = ['img', 'object', 'area', 'input[type="image"]'];
24var schema = (0, _schemas.generateObjSchema)({
25 elements: _schemas.arraySchema,
26 img: _schemas.arraySchema,
27 object: _schemas.arraySchema,
28 area: _schemas.arraySchema,
29 'input[type="image"]': _schemas.arraySchema
30});
31var ariaLabelHasValue = function ariaLabelHasValue(prop) {
32 var value = (0, _jsxAstUtils.getPropValue)(prop);
33 if (value === undefined) {
34 return false;
35 }
36 if (typeof value === 'string' && value.length === 0) {
37 return false;
38 }
39 return true;
40};
41var ruleByElement = {
42 img(context, node, nodeType) {
43 var altProp = (0, _jsxAstUtils.getProp)(node.attributes, 'alt');
44
45 // Missing alt prop error.
46 if (altProp === undefined) {
47 if ((0, _isPresentationRole["default"])(nodeType, node.attributes)) {
48 context.report({
49 node,
50 message: 'Prefer alt="" over a presentational role. First rule of aria is to not use aria if it can be achieved via native HTML.'
51 });
52 return;
53 }
54 // Check for `aria-label` to provide text alternative
55 // Don't create an error if the attribute is used correctly. But if it
56 // isn't, suggest that the developer use `alt` instead.
57 var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
58 if (ariaLabelProp !== undefined) {
59 if (!ariaLabelHasValue(ariaLabelProp)) {
60 context.report({
61 node,
62 message: 'The aria-label attribute must have a value. The alt attribute is preferred over aria-label for images.'
63 });
64 }
65 return;
66 }
67 // Check for `aria-labelledby` to provide text alternative
68 // Don't create an error if the attribute is used correctly. But if it
69 // isn't, suggest that the developer use `alt` instead.
70 var ariaLabelledbyProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
71 if (ariaLabelledbyProp !== undefined) {
72 if (!ariaLabelHasValue(ariaLabelledbyProp)) {
73 context.report({
74 node,
75 message: 'The aria-labelledby attribute must have a value. The alt attribute is preferred over aria-labelledby for images.'
76 });
77 }
78 return;
79 }
80 context.report({
81 node,
82 message: "".concat(nodeType, " elements must have an alt prop, either with meaningful text, or an empty string for decorative images.")
83 });
84 return;
85 }
86
87 // Check if alt prop is undefined.
88 var altValue = (0, _jsxAstUtils.getPropValue)(altProp);
89 var isNullValued = altProp.value === null; // <img alt />
90
91 if (altValue && !isNullValued || altValue === '') {
92 return;
93 }
94
95 // Undefined alt prop error.
96 context.report({
97 node,
98 message: "Invalid alt value for ".concat(nodeType, ". Use alt=\"\" for presentational images.")
99 });
100 },
101 object(context, node, unusedNodeType, elementType) {
102 var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
103 var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
104 var hasLabel = ariaLabelHasValue(ariaLabelProp) || ariaLabelHasValue(arialLabelledByProp);
105 var titleProp = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'title'));
106 var hasTitleAttr = !!titleProp;
107 if (hasLabel || hasTitleAttr || (0, _hasAccessibleChild["default"])(node.parent, elementType)) {
108 return;
109 }
110 context.report({
111 node,
112 message: 'Embedded <object> elements must have alternative text by providing inner text, aria-label or aria-labelledby props.'
113 });
114 },
115 area(context, node) {
116 var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
117 var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
118 var hasLabel = ariaLabelHasValue(ariaLabelProp) || ariaLabelHasValue(arialLabelledByProp);
119 if (hasLabel) {
120 return;
121 }
122 var altProp = (0, _jsxAstUtils.getProp)(node.attributes, 'alt');
123 if (altProp === undefined) {
124 context.report({
125 node,
126 message: 'Each area of an image map must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
127 });
128 return;
129 }
130 var altValue = (0, _jsxAstUtils.getPropValue)(altProp);
131 var isNullValued = altProp.value === null; // <area alt />
132
133 if (altValue && !isNullValued || altValue === '') {
134 return;
135 }
136 context.report({
137 node,
138 message: 'Each area of an image map must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
139 });
140 },
141 'input[type="image"]': function inputImage(context, node, nodeType) {
142 // Only test input[type="image"]
143 if (nodeType === 'input') {
144 var typePropValue = (0, _jsxAstUtils.getPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'type'));
145 if (typePropValue !== 'image') {
146 return;
147 }
148 }
149 var ariaLabelProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-label');
150 var arialLabelledByProp = (0, _jsxAstUtils.getProp)(node.attributes, 'aria-labelledby');
151 var hasLabel = ariaLabelHasValue(ariaLabelProp) || ariaLabelHasValue(arialLabelledByProp);
152 if (hasLabel) {
153 return;
154 }
155 var altProp = (0, _jsxAstUtils.getProp)(node.attributes, 'alt');
156 if (altProp === undefined) {
157 context.report({
158 node,
159 message: '<input> elements with type="image" must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
160 });
161 return;
162 }
163 var altValue = (0, _jsxAstUtils.getPropValue)(altProp);
164 var isNullValued = altProp.value === null; // <area alt />
165
166 if (altValue && !isNullValued || altValue === '') {
167 return;
168 }
169 context.report({
170 node,
171 message: '<input> elements with type="image" must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.'
172 });
173 }
174};
175var _default = exports["default"] = {
176 meta: {
177 docs: {
178 url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/alt-text.md',
179 description: 'Enforce all elements that require alternative text have meaningful information to relay back to end user.'
180 },
181 schema: [schema]
182 },
183 create: function create(context) {
184 var options = context.options[0] || {};
185 // Elements to validate for alt text.
186 var elementOptions = options.elements || DEFAULT_ELEMENTS;
187 // Get custom components for just the elements that will be tested.
188 var customComponents = (0, _arrayPrototype["default"])(elementOptions, function (element) {
189 return options[element];
190 });
191 var typesToValidate = new Set([].concat(customComponents, elementOptions).map(function (type) {
192 return type === 'input[type="image"]' ? 'input' : type;
193 }));
194 var elementType = (0, _getElementType["default"])(context);
195 return {
196 JSXOpeningElement(node) {
197 var nodeType = elementType(node);
198 if (!typesToValidate.has(nodeType)) {
199 return;
200 }
201 var DOMElement = nodeType;
202 if (DOMElement === 'input') {
203 DOMElement = 'input[type="image"]';
204 }
205
206 // Map nodeType to the DOM element if we are running this on a custom component.
207 if (elementOptions.indexOf(DOMElement) === -1) {
208 DOMElement = elementOptions.find(function (element) {
209 var customComponentsForElement = options[element] || [];
210 return customComponentsForElement.indexOf(nodeType) > -1;
211 });
212 }
213 ruleByElement[DOMElement](context, node, nodeType, elementType);
214 }
215 };
216 }
217};
218module.exports = exports.default;
Note: See TracBrowser for help on using the repository browser.