Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Commit

Permalink
[Issue #234] ARIA Rules - Fixed getImplicitRole for openingElements
Browse files Browse the repository at this point in the history
* added opening element support in getImplicitRole
* changed case of all HTML elements names from upper to lower
* exposed JsxAttribute functions for testability
  • Loading branch information
t-ligu authored and HamletDRC committed Sep 9, 2016
1 parent fb77883 commit e20c98a
Show file tree
Hide file tree
Showing 52 changed files with 331 additions and 136 deletions.
44 changes: 42 additions & 2 deletions src/utils/JsxAttribute.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/**
* @copyright Microsoft Corporation. All rights reserved.
*
* @JsxAttribute utilities for react rules.
*/

Expand Down Expand Up @@ -127,3 +125,45 @@ export function getJsxAttributesFromJsxElement(node: ts.Node): { [propName: stri

return attributesDictionary;
}

/**
* Get first JsxElement whose tagName equals tagName from code.
* @param code - a string of jsx code.
* @param exceptTagName - the element's tagName you want to get.
* @return { ts.JsxElement | ts.JsxSelfClosingElement } - a element.
*/
export function getJsxElementFromCode(code: string, exceptTagName: string): ts.JsxElement | ts.JsxSelfClosingElement {
const sourceFile: ts.SourceFile = ts.createSourceFile('test.tsx', code, ts.ScriptTarget.ES6, true);

return delintNode(sourceFile, exceptTagName);
}

function delintNode(node: ts.Node, tagName: string): ts.JsxElement | ts.JsxSelfClosingElement {
if (isJsxElement(node) && node.openingElement.tagName.getText() === tagName) {
return node;
} else if (isJsxSelfClosingElement(node) && node.tagName.getText() === tagName) {
return node;
} else if (!node || node.getChildCount() === 0) {
return undefined;
}

return ts.forEachChild(node, (childNode: ts.Node) => delintNode(childNode, tagName));
}

/**
* Get ancestor node whose tagName is ancestorTagName for a node.
* @return { ts.JsxElement } the ancestor node or undefined if the ancestor node is not exist.
*/
export function getAncestorNode(node: ts.Node, ancestorTagName: string): ts.JsxElement {
if (!node) {
return undefined;
}

const ancestorNode: ts.Node = node.parent;

if (isJsxElement(ancestorNode) && ancestorNode.openingElement.tagName.getText() === ancestorTagName) {
return ancestorNode;
} else {
return getAncestorNode(ancestorNode, ancestorTagName);
}
}
11 changes: 8 additions & 3 deletions src/utils/getImplicitRole.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as ts from 'typescript';
import * as implicitRoles from './implicitRoles';
import { isJsxElement, isJsxSelfClosingElement } from './TypeGuard';
import { isJsxElement, isJsxSelfClosingElement, isJsxOpeningElement } from './TypeGuard';

/**
* @returns the implicit role for a JsxElement, JsxSelfClosingElement or JsxOpeningElement.
* @returns { string } the implicit role or undefined if no corresponding role for a
* JsxElement, JsxSelfClosingElement or JsxOpeningElement.
* The implementation is inspired and re-implemented from
* https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/src/util/getImplicitRole.js
* A reference about implicit role: https://www.w3.org/TR/html-aria/#sec-strong-native-semantics.
* A reference about no corresponding role: https://www.w3.org/TR/html-aria/#dfn-no-corresponding-role.
*/
export function getImplicitRole(node: ts.Node): string {
let tagName: string;
Expand All @@ -14,9 +17,11 @@ export function getImplicitRole(node: ts.Node): string {
tagName = node.openingElement.tagName.getText();
} else if (isJsxSelfClosingElement(node)) {
tagName = node.tagName.getText();
} else if (isJsxOpeningElement(node)) {
tagName = node.tagName.getText();
} else {
tagName = undefined;
}

return tagName && implicitRoles[tagName.toUpperCase()] && implicitRoles[tagName.toUpperCase()](node);
return tagName && implicitRoles[tagName] && implicitRoles[tagName](node);
}
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/a.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ function getImplicitRoleForAnchor(node: ts.Node): string {
return getJsxAttributesFromJsxElement(node)[hrefString] ? 'link' : undefined;
}

export { getImplicitRoleForAnchor as A };
export { getImplicitRoleForAnchor as a };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ function getImplicitRoleForArea(node: ts.Node): string {
return getJsxAttributesFromJsxElement(node)[hrefString] ? 'link' : undefined;
}

export { getImplicitRoleForArea as AREA };
export { getImplicitRoleForArea as area };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/article.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForArticle(): string {
return 'article';
}

export { getImplicitRoleForArticle as ARTICLE };
export { getImplicitRoleForArticle as article };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/aside.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForAside(): string {
return 'complementary';
}

export { getImplicitRoleForAside as ASIDE };
export { getImplicitRoleForAside as aside };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForBody(): string {
return 'document';
}

export { getImplicitRoleForBody as BODY };
export { getImplicitRoleForBody as body };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForButton(): string {
return 'button';
}

export { getImplicitRoleForButton as BUTTON };
export { getImplicitRoleForButton as button };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/datalist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForDatalist(): string {
return 'listbox';
}

export { getImplicitRoleForDatalist as DATALIST };
export { getImplicitRoleForDatalist as datalist };
8 changes: 8 additions & 0 deletions src/utils/implicitRoles/dd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @Returns the implicit role for a dd tag.
*/
function getImplicitRoleForDd(): string {
return 'definition';
}

export { getImplicitRoleForDd as dd };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForDetails(): string {
return 'group';
}

export { getImplicitRoleForDetails as DETAILS };
export { getImplicitRoleForDetails as details };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForDialog(): string {
return 'dialog';
}

export { getImplicitRoleForDialog as DIALOG };
export { getImplicitRoleForDialog as dialog };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/dl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForDl(): string {
return 'list';
}

export { getImplicitRoleForDl as DL };
export { getImplicitRoleForDl as dl };
8 changes: 8 additions & 0 deletions src/utils/implicitRoles/dt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @Returns the implicit role for a dt tag.
*/
function getImplicitRoleForDt(): string {
return 'listitem';
}

export { getImplicitRoleForDt as dt };
11 changes: 11 additions & 0 deletions src/utils/implicitRoles/footer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as ts from 'typescript';
import { getAncestorNode } from '../JsxAttribute';

/**
* @Returns the implicit role for a footer tag.
*/
function getImplicitRoleForFooter(node: ts.Node): string {
return getAncestorNode(node, 'article') || getAncestorNode(node, 'section') ? undefined : 'contentinfo';
}

export { getImplicitRoleForFooter as footer };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForForm(): string {
return 'form';
}

export { getImplicitRoleForForm as FORM };
export { getImplicitRoleForForm as form };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/h1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForH1(): string {
return 'heading';
}

export { getImplicitRoleForH1 as H1 };
export { getImplicitRoleForH1 as h1 };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/h2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForH2(): string {
return 'heading';
}

export { getImplicitRoleForH2 as H2 };
export { getImplicitRoleForH2 as h2 };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/h3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForH3(): string {
return 'heading';
}

export { getImplicitRoleForH3 as H3 };
export { getImplicitRoleForH3 as h3 };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/h4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForH4(): string {
return 'heading';
}

export { getImplicitRoleForH4 as H4 };
export { getImplicitRoleForH4 as h4 };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/h5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForH5(): string {
return 'heading';
}

export { getImplicitRoleForH5 as H5 };
export { getImplicitRoleForH5 as h5 };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/h6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForH6(): string {
return 'heading';
}

export { getImplicitRoleForH6 as H6 };
export { getImplicitRoleForH6 as h6 };
11 changes: 11 additions & 0 deletions src/utils/implicitRoles/header.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as ts from 'typescript';
import { getAncestorNode } from '../JsxAttribute';

/**
* @Returns the implicit role for a header tag.
*/
function getImplicitRoleForHeader(node: ts.Node): string {
return getAncestorNode(node, 'article') || getAncestorNode(node, 'section') ? undefined : 'banner';
}

export { getImplicitRoleForHeader as header };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/hr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ function getImplicitRoleForHr(): string {
return 'separator';
}

export { getImplicitRoleForHr as HR };
export { getImplicitRoleForHr as hr };
2 changes: 1 addition & 1 deletion src/utils/implicitRoles/img.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ function getImplicitRoleForImg(node: ts.Node): string {
return 'presentation';
}

export { getImplicitRoleForImg as IMG };
export { getImplicitRoleForImg as img };
Loading

0 comments on commit e20c98a

Please sign in to comment.