Skip to content

Commit 351fd16

Browse files
authored
Merge pull request #119 from microsoft/ajayagr/port-rules-to-ts
chore: port all existing rules and tests to ts format
2 parents 0b06bfc + b64b59b commit 351fd16

File tree

119 files changed

+1425
-1824
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+1425
-1824
lines changed

dist/lib/index.js

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
77
Object.defineProperty(exports, "__esModule", { value: true });
88
console.log("Loading my-eslint-plugin");
99
const prefer_aria_over_title_attribute_1 = __importDefault(require("./rules/prefer-aria-over-title-attribute"));
10+
const checkbox_needs_labelling_1 = __importDefault(require("./rules/checkbox-needs-labelling"));
11+
const image_button_missing_aria_1 = __importDefault(require("./rules/buttons/image-button-missing-aria"));
12+
const link_missing_labelling_1 = __importDefault(require("./rules/link-missing-labelling"));
13+
const input_components_require_accessible_name_1 = __importDefault(require("./rules/input-components-require-accessible-name"));
14+
const menu_item_needs_labelling_1 = __importDefault(require("./rules/menu-item-needs-labelling"));
15+
const switch_needs_labelling_1 = __importDefault(require("./rules/switch-needs-labelling"));
16+
const toolbar_missing_aria_1 = __importDefault(require("./rules/toolbar-missing-aria"));
17+
const combobox_needs_labelling_1 = __importDefault(require("./rules/combobox-needs-labelling"));
18+
const no_empty_components_1 = __importDefault(require("./rules/no-empty-components"));
19+
const accordion_header_needs_labelling_1 = __importDefault(require("./rules/accordion-header-needs-labelling"));
20+
const accordion_item_needs_header_and_panel_1 = __importDefault(require("./rules/accordion-item-needs-header-and-panel"));
21+
const compound_button_needs_labelling_1 = __importDefault(require("./rules/buttons/compound-button-needs-labelling"));
22+
const no_empty_buttons_1 = __importDefault(require("./rules/buttons/no-empty-buttons"));
23+
const spin_button_needs_labelling_1 = __importDefault(require("./rules/spin-button-needs-labelling"));
24+
const spin_button_unrecommended_labelling_1 = __importDefault(require("./rules/spin-button-unrecommended-labelling"));
25+
const breadcrumb_needs_labelling_1 = __importDefault(require("./rules/breadcrumb-needs-labelling"));
26+
const dropdown_needs_labelling_1 = __importDefault(require("./rules/dropdown-needs-labelling"));
27+
const tooltip_not_recommended_1 = __importDefault(require("./rules/tooltip-not-recommended"));
28+
const avatar_needs_name_1 = __importDefault(require("./rules/avatar-needs-name"));
29+
const radio_button_missing_label_1 = __importDefault(require("./rules/radio-button-missing-label"));
30+
const radiogroup_missing_label_1 = __importDefault(require("./rules/radiogroup-missing-label"));
31+
const dialogbody_needs_title_content_and_actions_1 = __importDefault(require("./rules/dialogbody-needs-title-content-and-actions"));
32+
const dialogsurface_needs_aria_1 = __importDefault(require("./rules/dialogsurface-needs-aria"));
33+
const spinner_needs_labelling_1 = __importDefault(require("./rules/spinner-needs-labelling"));
34+
const badge_needs_accessible_name_1 = __importDefault(require("./rules/badge-needs-accessible-name"));
35+
const progressbar_needs_labelling_1 = __importDefault(require("./rules/progressbar-needs-labelling"));
1036
//------------------------------------------------------------------------------
1137
// Requirements
1238
//------------------------------------------------------------------------------
@@ -16,33 +42,33 @@ const prefer_aria_over_title_attribute_1 = __importDefault(require("./rules/pref
1642
// import all rules in lib/rules
1743
module.exports = {
1844
rules: {
19-
"checkbox-needs-labelling": require("./rules/checkbox-needs-labelling"),
20-
"image-button-missing-aria": require("./rules/buttons/image-button-missing-aria"),
21-
"link-missing-labelling": require("./rules/link-missing-labelling"),
22-
"input-components-require-accessible-name": require("./rules/input-components-require-accessible-name"),
23-
"menu-item-needs-labelling": require("./rules/menu-item-needs-labelling"),
24-
"switch-needs-labelling": require("./rules/switch-needs-labelling"),
25-
"toolbar-missing-aria": require("./rules/toolbar-missing-aria"),
26-
"combobox-needs-labelling": require("./rules/combobox-needs-labelling"),
27-
"no-empty-components": require("./rules/no-empty-components"),
28-
"accordion-header-needs-labelling": require("./rules/accordion-header-needs-labelling"),
29-
"accordion-item-needs-header-and-panel": require("./rules/accordion-item-needs-header-and-panel"),
30-
"compound-button-needs-labelling": require("./rules/buttons/compound-button-needs-labelling"),
31-
"no-empty-buttons": require("./rules/buttons/no-empty-buttons"),
32-
"spin-button-needs-labelling": require("./rules/spin-button-needs-labelling"),
33-
"spin-button-unrecommended-labelling": require("./rules/spin-button-unrecommended-labelling"),
34-
"breadcrumb-needs-labelling": require("./rules/breadcrumb-needs-labelling"),
35-
"dropdown-needs-labelling": require("./rules/dropdown-needs-labelling"),
36-
"tooltip-not-recommended": require("./rules/tooltip-not-recommended"),
37-
"avatar-needs-name": require("./rules/avatar-needs-name"),
38-
"radio-button-missing-label": require("./rules/radio-button-missing-label"),
39-
"radiogroup-missing-label": require("./rules/radiogroup-missing-label"),
45+
"checkbox-needs-labelling": checkbox_needs_labelling_1.default,
46+
"image-button-missing-aria": image_button_missing_aria_1.default,
47+
"link-missing-labelling": link_missing_labelling_1.default,
48+
"input-components-require-accessible-name": input_components_require_accessible_name_1.default,
49+
"menu-item-needs-labelling": menu_item_needs_labelling_1.default,
50+
"switch-needs-labelling": switch_needs_labelling_1.default,
51+
"toolbar-missing-aria": toolbar_missing_aria_1.default,
52+
"combobox-needs-labelling": combobox_needs_labelling_1.default,
53+
"no-empty-components": no_empty_components_1.default,
54+
"accordion-header-needs-labelling": accordion_header_needs_labelling_1.default,
55+
"accordion-item-needs-header-and-panel": accordion_item_needs_header_and_panel_1.default,
56+
"compound-button-needs-labelling": compound_button_needs_labelling_1.default,
57+
"no-empty-buttons": no_empty_buttons_1.default,
58+
"spin-button-needs-labelling": spin_button_needs_labelling_1.default,
59+
"spin-button-unrecommended-labelling": spin_button_unrecommended_labelling_1.default,
60+
"breadcrumb-needs-labelling": breadcrumb_needs_labelling_1.default,
61+
"dropdown-needs-labelling": dropdown_needs_labelling_1.default,
62+
"tooltip-not-recommended": tooltip_not_recommended_1.default,
63+
"avatar-needs-name": avatar_needs_name_1.default,
64+
"radio-button-missing-label": radio_button_missing_label_1.default,
65+
"radiogroup-missing-label": radiogroup_missing_label_1.default,
4066
"prefer-aria-over-title-attribute": prefer_aria_over_title_attribute_1.default,
41-
"dialogbody-needs-title-content-and-actions": require("./rules/dialogbody-needs-title-content-and-actions"),
42-
"dialogsurface-needs-aria": require("./rules/dialogsurface-needs-aria"),
43-
"spinner-needs-labelling": require("./rules/spinner-needs-labelling"),
44-
"badge-needs-accessible-name": require("./rules/badge-needs-accessible-name"),
45-
"progressbar-needs-labelling": require("./rules/progressbar-needs-labelling")
67+
"dialogbody-needs-title-content-and-actions": dialogbody_needs_title_content_and_actions_1.default,
68+
"dialogsurface-needs-aria": dialogsurface_needs_aria_1.default,
69+
"spinner-needs-labelling": spinner_needs_labelling_1.default,
70+
"badge-needs-accessible-name": badge_needs_accessible_name_1.default,
71+
"progressbar-needs-labelling": progressbar_needs_labelling_1.default
4672
},
4773
configs: {
4874
recommended: {
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
declare const _exports: import("eslint").Rule.RuleModule;
2-
export = _exports;
1+
import { TSESTree } from "@typescript-eslint/utils";
2+
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"missingAriaLabel", [], {
3+
JSXElement(node: TSESTree.JSXElement): void;
4+
}>;
5+
export default rule;
Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
1+
"use strict";
12
// Copyright (c) Microsoft Corporation.
23
// Licensed under the MIT License.
3-
"use strict";
4-
const { hasNonEmptyProp } = require("../util/hasNonEmptyProp");
5-
const { hasToolTipParent } = require("../util/hasTooltipParent");
6-
const { hasTextContentChild } = require("../util/hasTextContentChild");
7-
const { hasAssociatedLabelViaAriaLabelledBy } = require("../util/labelUtils");
8-
var hasProp = require("jsx-ast-utils").hasProp;
9-
var elementType = require("jsx-ast-utils").elementType;
4+
Object.defineProperty(exports, "__esModule", { value: true });
5+
const utils_1 = require("@typescript-eslint/utils");
6+
const jsx_ast_utils_1 = require("jsx-ast-utils");
7+
const hasNonEmptyProp_1 = require("../util/hasNonEmptyProp");
8+
const hasTooltipParent_1 = require("../util/hasTooltipParent");
9+
const hasTextContentChild_1 = require("../util/hasTextContentChild");
10+
const labelUtils_1 = require("../util/labelUtils");
1011
//------------------------------------------------------------------------------
1112
// Rule Definition
1213
//------------------------------------------------------------------------------
13-
/** @type {import('eslint').Rule.RuleModule} */
14-
module.exports = {
14+
const rule = utils_1.ESLintUtils.RuleCreator.withoutDocs({
15+
defaultOptions: [],
1516
meta: {
1617
messages: {
1718
missingAriaLabel: "Accessibility: the accordion header must have an accessible name"
1819
},
1920
type: "problem", // `problem`, `suggestion`, or `layout`
2021
docs: {
2122
description: "The accordion header is a button and it needs an accessibile name e.g. text content, aria-label, aria-labelledby.",
22-
recommended: false,
23-
url: null // URL to the documentation page for this rule
23+
recommended: false
2424
},
25-
fixable: null, // Or `code` or `whitespace`
2625
schema: [] // Add a schema if the rule has options
2726
},
2827
// create (function) returns an object with methods that ESLint calls to “visit” nodes while traversing the abstract syntax tree
@@ -32,26 +31,27 @@ module.exports = {
3231
JSXElement(node) {
3332
const openingElement = node.openingElement;
3433
// if it is not a AccordionHeader, return
35-
if (elementType(openingElement) !== "AccordionHeader") {
34+
if ((0, jsx_ast_utils_1.elementType)(openingElement) !== "AccordionHeader") {
3635
return;
3736
}
3837
// if it has text content, return
39-
if (hasTextContentChild(node)) {
38+
if ((0, hasTextContentChild_1.hasTextContentChild)(node)) {
4039
return;
4140
}
4241
// if it is not an icon button, return
43-
if (!hasProp(openingElement.attributes, "icon") && !hasProp(openingElement.attributes, "expandIcon")) {
42+
if (!(0, jsx_ast_utils_1.hasProp)(openingElement.attributes, "icon") &&
43+
!(0, jsx_ast_utils_1.hasProp)(openingElement.attributes, "expandIcon")) {
4444
return;
4545
}
4646
// if it has a tooltip parent, return
47-
if (hasToolTipParent(context)) {
47+
if ((0, hasTooltipParent_1.hasToolTipParent)(context)) {
4848
return;
4949
}
5050
// the button has an associated label
51-
if (hasAssociatedLabelViaAriaLabelledBy(openingElement, context)) {
51+
if ((0, labelUtils_1.hasAssociatedLabelViaAriaLabelledBy)(openingElement, context)) {
5252
return;
5353
}
54-
const hasAccessibleLabelling = hasNonEmptyProp(openingElement.attributes, "title") || hasNonEmptyProp(openingElement.attributes, "aria-label");
54+
const hasAccessibleLabelling = (0, hasNonEmptyProp_1.hasNonEmptyProp)(openingElement.attributes, "title") || (0, hasNonEmptyProp_1.hasNonEmptyProp)(openingElement.attributes, "aria-label");
5555
// if it has no accessible name, report error
5656
if (!hasAccessibleLabelling) {
5757
context.report({
@@ -62,4 +62,5 @@ module.exports = {
6262
}
6363
};
6464
}
65-
};
65+
});
66+
exports.default = rule;
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
declare const _exports: import("eslint").Rule.RuleModule;
2-
export = _exports;
1+
import { TSESTree } from "@typescript-eslint/utils";
2+
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"accordionItemOneHeaderOnePanel", [], {
3+
JSXOpeningElement(node: TSESTree.JSXOpeningElement): void;
4+
}>;
5+
export default rule;
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,39 @@
1+
"use strict";
12
// Copyright (c) Microsoft Corporation.
23
// Licensed under the MIT License.
3-
"use strict";
4+
Object.defineProperty(exports, "__esModule", { value: true });
5+
const utils_1 = require("@typescript-eslint/utils");
46
//------------------------------------------------------------------------------
57
// Rule Definition
68
//------------------------------------------------------------------------------
7-
/** @type {import('eslint').Rule.RuleModule} */
8-
module.exports = {
9+
const rule = utils_1.ESLintUtils.RuleCreator.withoutDocs({
10+
defaultOptions: [],
911
meta: {
1012
messages: {
1113
accordionItemOneHeaderOnePanel: "ensure AccordionItem has exactly one header and one panel"
1214
},
1315
type: "problem", // `problem`, `suggestion`, or `layout`
1416
docs: {
1517
description: "An AccordionItem needs exactly one header and one panel",
16-
recommended: true,
18+
recommended: "strict",
1719
url: "https://www.w3.org/WAI/ARIA/apg/patterns/accordion/" // URL to the documentation page for this rule
1820
},
19-
fixable: null, // Or `code` or `whitespace`
2021
schema: [] // Add a schema if the rule has options
2122
},
2223
create(context) {
2324
return {
2425
JSXOpeningElement(node) {
25-
if (node.name.name !== "AccordionItem") {
26+
if (node.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier && node.name.name !== "AccordionItem") {
27+
return;
28+
}
29+
if (!(node.parent && node.parent.type === utils_1.AST_NODE_TYPES.JSXElement)) {
2630
return;
2731
}
2832
const children = node.parent.children.filter(child => child.type === "JSXElement");
29-
const hasOneHeader = children.filter(child => child.openingElement.name.name === "AccordionHeader").length === 1;
30-
const hasOnePanel = children.filter(child => child.openingElement.name.name === "AccordionPanel").length === 1;
33+
const hasOneHeader = children.filter(child => child.openingElement.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
34+
child.openingElement.name.name === "AccordionHeader").length === 1;
35+
const hasOnePanel = children.filter(child => child.openingElement.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
36+
child.openingElement.name.name === "AccordionPanel").length === 1;
3137
if (!hasOneHeader || !hasOnePanel || children.length !== 2) {
3238
context.report({
3339
node,
@@ -37,4 +43,5 @@ module.exports = {
3743
}
3844
};
3945
}
40-
};
46+
});
47+
exports.default = rule;

dist/lib/rules/avatar-needs-name.d.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
export namespace meta {
2-
namespace messages {
3-
let missingAriaLabel: string;
4-
}
5-
let type: string;
6-
namespace docs {
7-
let description: string;
8-
let recommended: boolean;
9-
let url: string;
10-
}
11-
let schema: never[];
12-
}
13-
export function create(context: any): {
14-
JSXOpeningElement(node: any): void;
15-
};
1+
import { TSESTree } from "@typescript-eslint/utils";
2+
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"missingAriaLabel", [], {
3+
JSXOpeningElement(node: TSESTree.JSXOpeningElement): void;
4+
}>;
5+
export default rule;

dist/lib/rules/avatar-needs-name.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1+
"use strict";
12
// Copyright (c) Microsoft Corporation.
23
// Licensed under the MIT License.
3-
"use strict";
4-
const { hasNonEmptyProp } = require("../util/hasNonEmptyProp");
5-
var elementType = require("jsx-ast-utils").elementType;
6-
const { hasAssociatedLabelViaAriaLabelledBy } = require("../util/labelUtils");
4+
Object.defineProperty(exports, "__esModule", { value: true });
5+
const utils_1 = require("@typescript-eslint/utils");
6+
const jsx_ast_utils_1 = require("jsx-ast-utils");
7+
const hasNonEmptyProp_1 = require("../util/hasNonEmptyProp");
8+
const labelUtils_1 = require("../util/labelUtils");
79
//------------------------------------------------------------------------------
810
// Rule Definition
911
//------------------------------------------------------------------------------
10-
module.exports = {
12+
const rule = utils_1.ESLintUtils.RuleCreator.withoutDocs({
13+
defaultOptions: [],
1114
meta: {
1215
// possible error messages for the rule
1316
messages: {
@@ -19,7 +22,7 @@ module.exports = {
1922
docs: {
2023
// DONE
2124
description: "Accessibility: Avatar must have an accessible labelling: name, aria-label, aria-labelledby",
22-
recommended: true,
25+
recommended: "strict",
2326
url: "https://www.w3.org/TR/html-aria/" // URL to the documentation page for this rule
2427
},
2528
schema: []
@@ -30,13 +33,13 @@ module.exports = {
3033
// visitor functions for different types of nodes
3134
JSXOpeningElement(node) {
3235
// if it is not an Avatar, return
33-
if (elementType(node) !== "Avatar") {
36+
if ((0, jsx_ast_utils_1.elementType)(node) !== "Avatar") {
3437
return;
3538
}
3639
// if the Avatar has a name, aria-label or aria-labelledby, return
37-
if (hasNonEmptyProp(node.attributes, "name") ||
38-
hasNonEmptyProp(node.attributes, "aria-label") ||
39-
hasAssociatedLabelViaAriaLabelledBy(node, context)) {
40+
if ((0, hasNonEmptyProp_1.hasNonEmptyProp)(node.attributes, "name") ||
41+
(0, hasNonEmptyProp_1.hasNonEmptyProp)(node.attributes, "aria-label") ||
42+
(0, labelUtils_1.hasAssociatedLabelViaAriaLabelledBy)(node, context)) {
4043
return;
4144
}
4245
// no aria
@@ -47,4 +50,5 @@ module.exports = {
4750
}
4851
};
4952
}
50-
};
53+
});
54+
exports.default = rule;
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
declare const _exports: import("eslint").Rule.RuleModule;
2-
export = _exports;
1+
import { TSESTree } from "@typescript-eslint/utils";
2+
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"noAriaDescribedbyAsLabel", [], {
3+
JSXElement(node: TSESTree.JSXElement): void;
4+
}>;
5+
export default rule;

0 commit comments

Comments
 (0)