Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 43902f7

Browse filesBrowse files
mohammedzamakhanmgechev
authored andcommitted
feat(rule): tabindex should not be positive (#744)
1 parent e7b2fa7 commit 43902f7
Copy full SHA for 43902f7

4 files changed

+127Lines changed: 127 additions & 0 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/index.ts‎

Copy file name to clipboardExpand all lines: src/index.ts
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export { Rule as PreferInlineDecorator } from './preferInlineDecoratorRule';
2828
export { Rule as PreferOutputReadonlyRule } from './preferOutputReadonlyRule';
2929
export { Rule as TemplateConditionalComplexityRule } from './templateConditionalComplexityRule';
3030
export { Rule as TemplateCyclomaticComplexityRule } from './templateCyclomaticComplexityRule';
31+
export { Rule as TemplateAccessibilityTabindexNoPositiveRule } from './templateAccessibilityTabindexNoPositiveRule';
3132
export { Rule as TemplatesNoNegatedAsync } from './templatesNoNegatedAsyncRule';
3233
export { Rule as TrackByFunctionRule } from './trackByFunctionRule';
3334
export { Rule as UseHostPropertyDecoratorRule } from './useHostPropertyDecoratorRule';
Collapse file
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { ElementAst } from '@angular/compiler';
2+
import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib';
3+
import { SourceFile } from 'typescript/lib/typescript';
4+
import { NgWalker } from './angular/ngWalker';
5+
import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor';
6+
import { getAttributeValue } from './util/getAttributeValue';
7+
8+
export class Rule extends Rules.AbstractRule {
9+
static readonly metadata: IRuleMetadata = {
10+
description: 'Ensures that the tab index is not positive',
11+
options: null,
12+
optionsDescription: 'Not configurable.',
13+
rationale: 'positive values for tabidex attribute should be avoided because they mess up with the order of focus (AX_FOCUS_03)',
14+
ruleName: 'template-accessibility-tabindex-no-positive',
15+
type: 'functionality',
16+
typescriptOnly: true
17+
};
18+
19+
static readonly FAILURE_MESSAGE = 'Tabindex cannot be positive';
20+
21+
apply(sourceFile: SourceFile): RuleFailure[] {
22+
return this.applyWithWalker(
23+
new NgWalker(sourceFile, this.getOptions(), {
24+
templateVisitorCtrl: TemplateAccessibilityTabindexNoPositiveVisitor
25+
})
26+
);
27+
}
28+
}
29+
30+
class TemplateAccessibilityTabindexNoPositiveVisitor extends BasicTemplateAstVisitor {
31+
visitElement(ast: ElementAst, context: any): any {
32+
this.validateElement(ast);
33+
super.visitElement(ast, context);
34+
}
35+
36+
private validateElement(element: ElementAst) {
37+
let tabIndexValue = getAttributeValue(element, 'tabindex');
38+
if (tabIndexValue) {
39+
tabIndexValue = parseInt(tabIndexValue, 10);
40+
if (tabIndexValue > 0) {
41+
const {
42+
sourceSpan: {
43+
end: { offset: endOffset },
44+
start: { offset: startOffset }
45+
}
46+
} = element;
47+
this.addFailureFromStartToEnd(startOffset, endOffset, Rule.FAILURE_MESSAGE);
48+
}
49+
}
50+
}
51+
}
Collapse file

‎src/util/getAttributeValue.ts‎

Copy file name to clipboard
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ElementAst } from '@angular/compiler';
2+
3+
export const getAttributeValue = (element: ElementAst, property: string) => {
4+
const attr = element.attrs.find(attr => attr.name === property);
5+
const input = element.inputs.find(input => input.name === property);
6+
if (attr) {
7+
return attr.value;
8+
}
9+
if (input) {
10+
return (<any>input.value).ast.value;
11+
}
12+
};
Collapse file
+63Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Rule } from '../src/templateAccessibilityTabindexNoPositiveRule';
2+
import { assertAnnotated, assertSuccess } from './testHelper';
3+
4+
const {
5+
FAILURE_MESSAGE,
6+
metadata: { ruleName }
7+
} = Rule;
8+
9+
describe(ruleName, () => {
10+
describe('failure', () => {
11+
it('should fail when tabindex attr is positive', () => {
12+
const source = `
13+
@Component({
14+
template: \`
15+
<div tabindex="5"></div>
16+
~~~~~~~~~~~~~~~~~~
17+
\`
18+
})
19+
class Bar {}
20+
`;
21+
assertAnnotated({
22+
message: FAILURE_MESSAGE,
23+
ruleName,
24+
source
25+
});
26+
});
27+
28+
it('should fail when tabindex input is positive', () => {
29+
const source = `
30+
@Component({
31+
template: \`
32+
<div [attr.tabindex]="1"></div>
33+
~~~~~~~~~~~~~~~~~~~~~~~~~
34+
\`
35+
})
36+
class Bar {}
37+
`;
38+
assertAnnotated({
39+
message: FAILURE_MESSAGE,
40+
ruleName,
41+
source
42+
});
43+
});
44+
});
45+
46+
describe('success', () => {
47+
it('should work with tab index is not positive', () => {
48+
const source = `
49+
@Component({
50+
template: \`
51+
<span tabindex="-1"></span>
52+
<span tabindex="0"></span>
53+
<span [attr.tabindex]="-1"></span>
54+
<span [attr.tabindex]="0"></span>
55+
<span [attr.tabindex]="tabIndex"></span>
56+
\`
57+
})
58+
class Bar {}
59+
`;
60+
assertSuccess(ruleName, source);
61+
});
62+
});
63+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.