UNPKG

5.36 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = Object.setPrototypeOf ||
4 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6 return function (d, b) {
7 extendStatics(d, b);
8 function __() { this.constructor = d; }
9 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10 };
11})();
12Object.defineProperty(exports, "__esModule", { value: true });
13var ts = require("typescript");
14var Lint = require("tslint");
15var getImplicitRole_1 = require("./utils/getImplicitRole");
16var JsxAttribute_1 = require("./utils/JsxAttribute");
17var ROLES_SCHEMA = require('./utils/attributes/roleSchema.json');
18var ROLES = ROLES_SCHEMA.roles;
19var ARIA_ATTRIBUTES = require('./utils/attributes/ariaSchema.json');
20var ROLE_STRING = 'role';
21var TAGS_WITH_ARIA_LEVEL = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
22function getFailureStringForNotImplicitRole(roleNamesInElement, missingProps) {
23 return "Element with ARIA role(s) '" + roleNamesInElement.join(', ') + "' are missing required attribute(s): " + missingProps.join(', ') + ". A reference to role definitions can be found at https://www.w3.org/TR/wai-aria/roles#role_definitions.";
24}
25exports.getFailureStringForNotImplicitRole = getFailureStringForNotImplicitRole;
26function getFailureStringForImplicitRole(tagName, roleNamesInElement, missingProps) {
27 return "Tag '" + tagName + "' has implicit role '" + roleNamesInElement + "'. It requires aria-* attributes: " + missingProps.join(', ') + " that are missing in the element. A reference to role definitions can be found at https://www.w3.org/TR/wai-aria/roles#role_definitions.";
28}
29exports.getFailureStringForImplicitRole = getFailureStringForImplicitRole;
30var Rule = (function (_super) {
31 __extends(Rule, _super);
32 function Rule() {
33 return _super !== null && _super.apply(this, arguments) || this;
34 }
35 Rule.prototype.apply = function (sourceFile) {
36 return sourceFile.languageVariant === ts.LanguageVariant.JSX
37 ? this.applyWithWalker(new A11yRoleHasRequiredAriaPropsWalker(sourceFile, this.getOptions()))
38 : [];
39 };
40 Rule.metadata = {
41 ruleName: 'react-a11y-role-has-required-aria-props',
42 type: 'maintainability',
43 description: 'Elements with aria roles must have all required attributes according to the role.',
44 options: null,
45 optionsDescription: '',
46 typescriptOnly: true,
47 issueClass: 'Non-SDL',
48 issueType: 'Warning',
49 severity: 'Important',
50 level: 'Opportunity for Excellence',
51 group: 'Accessibility'
52 };
53 return Rule;
54}(Lint.Rules.AbstractRule));
55exports.Rule = Rule;
56var A11yRoleHasRequiredAriaPropsWalker = (function (_super) {
57 __extends(A11yRoleHasRequiredAriaPropsWalker, _super);
58 function A11yRoleHasRequiredAriaPropsWalker() {
59 return _super !== null && _super.apply(this, arguments) || this;
60 }
61 A11yRoleHasRequiredAriaPropsWalker.prototype.visitJsxElement = function (node) {
62 this.checkJsxElement(node.openingElement);
63 _super.prototype.visitJsxElement.call(this, node);
64 };
65 A11yRoleHasRequiredAriaPropsWalker.prototype.visitJsxSelfClosingElement = function (node) {
66 this.checkJsxElement(node);
67 _super.prototype.visitJsxSelfClosingElement.call(this, node);
68 };
69 A11yRoleHasRequiredAriaPropsWalker.prototype.checkJsxElement = function (node) {
70 var tagName = node.tagName.getText();
71 var attributesInElement = JsxAttribute_1.getJsxAttributesFromJsxElement(node);
72 var roleProp = attributesInElement[ROLE_STRING];
73 var roleValue = roleProp ? JsxAttribute_1.getStringLiteral(roleProp) : getImplicitRole_1.getImplicitRole(node);
74 var isImplicitRole = !roleProp && !!roleValue;
75 var normalizedRoles = (roleValue || '').toLowerCase().split(' ')
76 .filter(function (role) { return !!ROLES[role]; });
77 if (normalizedRoles.length === 0) {
78 return;
79 }
80 var requiredAttributeNames = [];
81 normalizedRoles.forEach(function (role) {
82 requiredAttributeNames = requiredAttributeNames.concat(ROLES[role].requiredProps || []);
83 });
84 var attributeNamesInElement = Object.keys(attributesInElement)
85 .filter(function (attributeName) { return !!ARIA_ATTRIBUTES[attributeName.toLowerCase()]; })
86 .concat(TAGS_WITH_ARIA_LEVEL.indexOf(tagName) === -1 ? [] : ['aria-level']);
87 var missingAttributes = requiredAttributeNames
88 .filter(function (attributeName) { return attributeNamesInElement.indexOf(attributeName) === -1; });
89 if (missingAttributes.length > 0) {
90 this.addFailureAt(node.getStart(), node.getWidth(), isImplicitRole ?
91 getFailureStringForImplicitRole(node.tagName.getText(), normalizedRoles[0], missingAttributes) :
92 getFailureStringForNotImplicitRole(normalizedRoles, missingAttributes));
93 }
94 };
95 return A11yRoleHasRequiredAriaPropsWalker;
96}(Lint.RuleWalker));
97//# sourceMappingURL=reactA11yRoleHasRequiredAriaPropsRule.js.map
\No newline at end of file