UNPKG

4.56 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = function (d, b) {
4 extendStatics = Object.setPrototypeOf ||
5 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7 return extendStatics(d, b);
8 }
9 return function (d, b) {
10 extendStatics(d, b);
11 function __() { this.constructor = d; }
12 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13 };
14})();
15Object.defineProperty(exports, "__esModule", { value: true });
16var ts = require("typescript");
17var Lint = require("tslint");
18var tsutils = require("tsutils");
19var Utils_1 = require("./utils/Utils");
20var EMPTY_TITLE_FAILURE_STRING = 'Title elements must not be empty';
21var LONG_TITLE_FAILURE_STRING = 'Title length must not be longer than 60 characters';
22var WORD_TITLE_FAILURE_STRING = 'Title must contain more than one word';
23var MAX_TITLE_LENGTH = 60;
24var Rule = (function (_super) {
25 __extends(Rule, _super);
26 function Rule() {
27 return _super !== null && _super.apply(this, arguments) || this;
28 }
29 Rule.prototype.apply = function (sourceFile) {
30 if (sourceFile.languageVariant === ts.LanguageVariant.JSX) {
31 return this.applyWithFunction(sourceFile, walk);
32 }
33 else {
34 return [];
35 }
36 };
37 Rule.metadata = {
38 ruleName: 'react-a11y-titles',
39 type: 'functionality',
40 description: 'For accessibility of your website, HTML title elements must be concise and non-empty.',
41 rationale: "References:\n <ul>\n <li><a href=\"http://www.w3.org/TR/WCAG20/#navigation-mechanisms-title\">WCAG 2.0 - Requirement 2.4.2 Page Titled (Level A)</a></li>\n <li><a href=\"http://oaa-accessibility.org/wcag20/rule/13\">OAA-Accessibility Rule 13: Title element should not be empty</a></li>\n <li><a href=\"http://oaa-accessibility.org/wcag20/rule/24\">OAA-Accessibility Rule 24: Title content should be concise</a></li>\n <li><a href=\"http://oaa-accessibility.org/wcag20/rule/25\">OAA-Accessibility Rule 25: Title text must contain more than one word</a></li>\n </ul>",
42 options: null,
43 optionsDescription: '',
44 typescriptOnly: true,
45 issueClass: 'Non-SDL',
46 issueType: 'Warning',
47 severity: 'Moderate',
48 level: 'Opportunity for Excellence',
49 group: 'Accessibility'
50 };
51 return Rule;
52}(Lint.Rules.AbstractRule));
53exports.Rule = Rule;
54function walk(ctx) {
55 function validateTitleText(text, titleNode) {
56 if (text.length > MAX_TITLE_LENGTH) {
57 ctx.addFailureAt(titleNode.getStart(), titleNode.getWidth(), LONG_TITLE_FAILURE_STRING + ': ' + Utils_1.Utils.trimTo(text, 20));
58 }
59 else if (!(text.indexOf(' ') > 0)) {
60 ctx.addFailureAt(titleNode.getStart(), titleNode.getWidth(), WORD_TITLE_FAILURE_STRING + ': ' + Utils_1.Utils.trimTo(text, 20));
61 }
62 }
63 function cb(node) {
64 if (tsutils.isJsxSelfClosingElement(node)) {
65 if (node.tagName.getText() === 'title') {
66 ctx.addFailureAt(node.getStart(), node.getWidth(), EMPTY_TITLE_FAILURE_STRING);
67 }
68 }
69 else if (tsutils.isJsxElement(node)) {
70 if (node.openingElement.tagName.getText() === 'title') {
71 if (node.children.length === 0) {
72 ctx.addFailureAt(node.getStart(), node.getWidth(), EMPTY_TITLE_FAILURE_STRING);
73 }
74 else if (node.children.length === 1) {
75 if (node.children[0].kind === ts.SyntaxKind.JsxText) {
76 var value = node.children[0];
77 validateTitleText(value.getText(), node);
78 }
79 else if (node.children[0].kind === ts.SyntaxKind.JsxExpression) {
80 var exp = node.children[0];
81 if (exp.expression !== undefined && exp.expression.kind === ts.SyntaxKind.StringLiteral) {
82 validateTitleText(exp.expression.text, node);
83 }
84 }
85 }
86 }
87 }
88 return ts.forEachChild(node, cb);
89 }
90 return ts.forEachChild(ctx.sourceFile, cb);
91}
92//# sourceMappingURL=reactA11yTitlesRule.js.map
\No newline at end of file