tslint-microsoft-contrib
Version:
TSLint Rules for Microsoft
235 lines • 5.66 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript");
var Lint = require("tslint");
var tsutils = require("tsutils");
var FAILURE_MISSING_LANG = 'An html element is missing the lang attribute';
var FAILURE_WRONG_LANG_CODE = 'Lang attribute does not have a valid value. Found: ';
var LANGUAGE_CODES = [
'ab',
'aa',
'af',
'sq',
'am',
'ar',
'an',
'hy',
'as',
'ay',
'az',
'ba',
'eu',
'bn',
'dz',
'bh',
'bi',
'br',
'bg',
'my',
'be',
'km',
'ca',
'zh',
'zh-Hans',
'zh-Hant',
'co',
'hr',
'cs',
'da',
'nl',
'en',
'eo',
'et',
'fo',
'fa',
'fj',
'fi',
'fr',
'fy',
'gl',
'gd',
'gv',
'ka',
'de',
'el',
'kl',
'gn',
'gu',
'ht',
'ha',
'he',
'iw',
'hi',
'hu',
'is',
'io',
'id',
'in',
'ia',
'ie',
'iu',
'ik',
'ga',
'it',
'ja',
'jv',
'kn',
'ks',
'kk',
'rw',
'ky',
'rn',
'ko',
'ku',
'lo',
'la',
'lv',
'li',
'ln',
'lt',
'mk',
'mg',
'ms',
'ml',
'mt',
'mi',
'mr',
'mo',
'mn',
'na',
'ne',
'no',
'oc',
'or',
'om',
'ps',
'pl',
'pt',
'pa',
'qu',
'rm',
'ro',
'ru',
'sm',
'sg',
'sa',
'sr',
'sh',
'st',
'tn',
'sn',
'ii',
'sd',
'si',
'ss',
'sk',
'sl',
'so',
'es',
'su',
'sw',
'sv',
'tl',
'tg',
'ta',
'tt',
'te',
'th',
'bo',
'ti',
'to',
'ts',
'tr',
'tk',
'tw',
'ug',
'uk',
'ur',
'uz',
'vi',
'vo',
'wa',
'cy',
'wo',
'xh',
'yi',
'ji',
'yo',
'zu'
];
var Rule = (function (_super) {
__extends(Rule, _super);
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
}
Rule.prototype.apply = function (sourceFile) {
if (sourceFile.languageVariant === ts.LanguageVariant.JSX) {
return this.applyWithFunction(sourceFile, walk);
}
return [];
};
Rule.metadata = {
ruleName: 'react-a11y-lang',
type: 'functionality',
description: 'For accessibility of your website, html elements must have a valid lang attribute.',
rationale: "References:\n <ul>\n <li><a href=\"https://www.w3.org/TR/WCAG20-TECHS/H58.html\">\n H58: Using language attributes to identify changes in the human language\n </a></li>\n <li><a href=\"https://dequeuniversity.com/rules/axe/1.1/valid-lang\">\n lang attribute must have a valid value\n </a></li>\n <li><a href=\"https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes\">\n List of ISO 639-1 codes\n </a></li>\n </ul>",
options: null,
optionsDescription: '',
typescriptOnly: true,
issueClass: 'Non-SDL',
issueType: 'Warning',
severity: 'Low',
level: 'Opportunity for Excellence',
group: 'Accessibility'
};
return Rule;
}(Lint.Rules.AbstractRule));
exports.Rule = Rule;
function walk(ctx) {
function validateOpeningElement(parent, openingElement) {
if (openingElement.tagName.getText() === 'html') {
var attributes = openingElement.attributes;
var langFound_1 = false;
attributes.properties.forEach(function (attribute) {
if (attribute.kind === ts.SyntaxKind.JsxAttribute) {
if (attribute.name.getText() === 'lang') {
langFound_1 = true;
if (attribute.initializer !== undefined && attribute.initializer.kind === ts.SyntaxKind.StringLiteral) {
var langText = attribute.initializer.text;
if (LANGUAGE_CODES.indexOf(langText) === -1) {
ctx.addFailureAt(parent.getStart(), parent.getWidth(), FAILURE_WRONG_LANG_CODE + langText);
}
}
}
}
});
if (!langFound_1) {
ctx.addFailureAt(parent.getStart(), parent.getWidth(), FAILURE_MISSING_LANG);
}
}
}
function cb(node) {
if (tsutils.isJsxSelfClosingElement(node)) {
validateOpeningElement(node, node);
}
else if (tsutils.isJsxElement(node)) {
validateOpeningElement(node, node.openingElement);
}
return ts.forEachChild(node, cb);
}
return ts.forEachChild(ctx.sourceFile, cb);
}
//# sourceMappingURL=reactA11yLangRule.js.map