Skip to content

Commit

Permalink
Merge branch 'main' into user/harshmodi/FieldLintRule
Browse files Browse the repository at this point in the history
  • Loading branch information
Harsh-Modi278 committed Sep 20, 2024
2 parents b42e2f0 + 351fd16 commit f4cfee3
Show file tree
Hide file tree
Showing 119 changed files with 1,424 additions and 1,824 deletions.
78 changes: 52 additions & 26 deletions dist/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
console.log("Loading my-eslint-plugin");
const prefer_aria_over_title_attribute_1 = __importDefault(require("./rules/prefer-aria-over-title-attribute"));
const checkbox_needs_labelling_1 = __importDefault(require("./rules/checkbox-needs-labelling"));
const image_button_missing_aria_1 = __importDefault(require("./rules/buttons/image-button-missing-aria"));
const link_missing_labelling_1 = __importDefault(require("./rules/link-missing-labelling"));
const input_components_require_accessible_name_1 = __importDefault(require("./rules/input-components-require-accessible-name"));
const menu_item_needs_labelling_1 = __importDefault(require("./rules/menu-item-needs-labelling"));
const switch_needs_labelling_1 = __importDefault(require("./rules/switch-needs-labelling"));
const toolbar_missing_aria_1 = __importDefault(require("./rules/toolbar-missing-aria"));
const combobox_needs_labelling_1 = __importDefault(require("./rules/combobox-needs-labelling"));
const no_empty_components_1 = __importDefault(require("./rules/no-empty-components"));
const accordion_header_needs_labelling_1 = __importDefault(require("./rules/accordion-header-needs-labelling"));
const accordion_item_needs_header_and_panel_1 = __importDefault(require("./rules/accordion-item-needs-header-and-panel"));
const compound_button_needs_labelling_1 = __importDefault(require("./rules/buttons/compound-button-needs-labelling"));
const no_empty_buttons_1 = __importDefault(require("./rules/buttons/no-empty-buttons"));
const spin_button_needs_labelling_1 = __importDefault(require("./rules/spin-button-needs-labelling"));
const spin_button_unrecommended_labelling_1 = __importDefault(require("./rules/spin-button-unrecommended-labelling"));
const breadcrumb_needs_labelling_1 = __importDefault(require("./rules/breadcrumb-needs-labelling"));
const dropdown_needs_labelling_1 = __importDefault(require("./rules/dropdown-needs-labelling"));
const tooltip_not_recommended_1 = __importDefault(require("./rules/tooltip-not-recommended"));
const avatar_needs_name_1 = __importDefault(require("./rules/avatar-needs-name"));
const radio_button_missing_label_1 = __importDefault(require("./rules/radio-button-missing-label"));
const radiogroup_missing_label_1 = __importDefault(require("./rules/radiogroup-missing-label"));
const dialogbody_needs_title_content_and_actions_1 = __importDefault(require("./rules/dialogbody-needs-title-content-and-actions"));
const dialogsurface_needs_aria_1 = __importDefault(require("./rules/dialogsurface-needs-aria"));
const spinner_needs_labelling_1 = __importDefault(require("./rules/spinner-needs-labelling"));
const badge_needs_accessible_name_1 = __importDefault(require("./rules/badge-needs-accessible-name"));
const progressbar_needs_labelling_1 = __importDefault(require("./rules/progressbar-needs-labelling"));
const field_needs_labelling_1 = __importDefault(require("./rules/field-needs-labelling"));
//------------------------------------------------------------------------------
// Requirements
Expand All @@ -17,33 +43,33 @@ const field_needs_labelling_1 = __importDefault(require("./rules/field-needs-lab
// import all rules in lib/rules
module.exports = {
rules: {
"checkbox-needs-labelling": require("./rules/checkbox-needs-labelling"),
"image-button-missing-aria": require("./rules/buttons/image-button-missing-aria"),
"link-missing-labelling": require("./rules/link-missing-labelling"),
"input-components-require-accessible-name": require("./rules/input-components-require-accessible-name"),
"menu-item-needs-labelling": require("./rules/menu-item-needs-labelling"),
"switch-needs-labelling": require("./rules/switch-needs-labelling"),
"toolbar-missing-aria": require("./rules/toolbar-missing-aria"),
"combobox-needs-labelling": require("./rules/combobox-needs-labelling"),
"no-empty-components": require("./rules/no-empty-components"),
"accordion-header-needs-labelling": require("./rules/accordion-header-needs-labelling"),
"accordion-item-needs-header-and-panel": require("./rules/accordion-item-needs-header-and-panel"),
"compound-button-needs-labelling": require("./rules/buttons/compound-button-needs-labelling"),
"no-empty-buttons": require("./rules/buttons/no-empty-buttons"),
"spin-button-needs-labelling": require("./rules/spin-button-needs-labelling"),
"spin-button-unrecommended-labelling": require("./rules/spin-button-unrecommended-labelling"),
"breadcrumb-needs-labelling": require("./rules/breadcrumb-needs-labelling"),
"dropdown-needs-labelling": require("./rules/dropdown-needs-labelling"),
"tooltip-not-recommended": require("./rules/tooltip-not-recommended"),
"avatar-needs-name": require("./rules/avatar-needs-name"),
"radio-button-missing-label": require("./rules/radio-button-missing-label"),
"radiogroup-missing-label": require("./rules/radiogroup-missing-label"),
"checkbox-needs-labelling": checkbox_needs_labelling_1.default,
"image-button-missing-aria": image_button_missing_aria_1.default,
"link-missing-labelling": link_missing_labelling_1.default,
"input-components-require-accessible-name": input_components_require_accessible_name_1.default,
"menu-item-needs-labelling": menu_item_needs_labelling_1.default,
"switch-needs-labelling": switch_needs_labelling_1.default,
"toolbar-missing-aria": toolbar_missing_aria_1.default,
"combobox-needs-labelling": combobox_needs_labelling_1.default,
"no-empty-components": no_empty_components_1.default,
"accordion-header-needs-labelling": accordion_header_needs_labelling_1.default,
"accordion-item-needs-header-and-panel": accordion_item_needs_header_and_panel_1.default,
"compound-button-needs-labelling": compound_button_needs_labelling_1.default,
"no-empty-buttons": no_empty_buttons_1.default,
"spin-button-needs-labelling": spin_button_needs_labelling_1.default,
"spin-button-unrecommended-labelling": spin_button_unrecommended_labelling_1.default,
"breadcrumb-needs-labelling": breadcrumb_needs_labelling_1.default,
"dropdown-needs-labelling": dropdown_needs_labelling_1.default,
"tooltip-not-recommended": tooltip_not_recommended_1.default,
"avatar-needs-name": avatar_needs_name_1.default,
"radio-button-missing-label": radio_button_missing_label_1.default,
"radiogroup-missing-label": radiogroup_missing_label_1.default,
"prefer-aria-over-title-attribute": prefer_aria_over_title_attribute_1.default,
"dialogbody-needs-title-content-and-actions": require("./rules/dialogbody-needs-title-content-and-actions"),
"dialogsurface-needs-aria": require("./rules/dialogsurface-needs-aria"),
"spinner-needs-labelling": require("./rules/spinner-needs-labelling"),
"badge-needs-accessible-name": require("./rules/badge-needs-accessible-name"),
"progressbar-needs-labelling": require("./rules/progressbar-needs-labelling"),
"dialogbody-needs-title-content-and-actions": dialogbody_needs_title_content_and_actions_1.default,
"dialogsurface-needs-aria": dialogsurface_needs_aria_1.default,
"spinner-needs-labelling": spinner_needs_labelling_1.default,
"badge-needs-accessible-name": badge_needs_accessible_name_1.default,
"progressbar-needs-labelling": progressbar_needs_labelling_1.default,
"field-needs-labelling": field_needs_labelling_1.default
},
configs: {
Expand Down
7 changes: 5 additions & 2 deletions dist/lib/rules/accordion-header-needs-labelling.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
declare const _exports: import("eslint").Rule.RuleModule;
export = _exports;
import { TSESTree } from "@typescript-eslint/utils";
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"missingAriaLabel", [], {
JSXElement(node: TSESTree.JSXElement): void;
}>;
export default rule;
39 changes: 20 additions & 19 deletions dist/lib/rules/accordion-header-needs-labelling.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
"use strict";
const { hasNonEmptyProp } = require("../util/hasNonEmptyProp");
const { hasToolTipParent } = require("../util/hasTooltipParent");
const { hasTextContentChild } = require("../util/hasTextContentChild");
const { hasAssociatedLabelViaAriaLabelledBy } = require("../util/labelUtils");
var hasProp = require("jsx-ast-utils").hasProp;
var elementType = require("jsx-ast-utils").elementType;
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const jsx_ast_utils_1 = require("jsx-ast-utils");
const hasNonEmptyProp_1 = require("../util/hasNonEmptyProp");
const hasTooltipParent_1 = require("../util/hasTooltipParent");
const hasTextContentChild_1 = require("../util/hasTextContentChild");
const labelUtils_1 = require("../util/labelUtils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
const rule = utils_1.ESLintUtils.RuleCreator.withoutDocs({
defaultOptions: [],
meta: {
messages: {
missingAriaLabel: "Accessibility: the accordion header must have an accessible name"
},
type: "problem", // `problem`, `suggestion`, or `layout`
docs: {
description: "The accordion header is a button and it needs an accessibile name e.g. text content, aria-label, aria-labelledby.",
recommended: false,
url: null // URL to the documentation page for this rule
recommended: false
},
fixable: null, // Or `code` or `whitespace`
schema: [] // Add a schema if the rule has options
},
// create (function) returns an object with methods that ESLint calls to “visit” nodes while traversing the abstract syntax tree
Expand All @@ -32,26 +31,27 @@ module.exports = {
JSXElement(node) {
const openingElement = node.openingElement;
// if it is not a AccordionHeader, return
if (elementType(openingElement) !== "AccordionHeader") {
if ((0, jsx_ast_utils_1.elementType)(openingElement) !== "AccordionHeader") {
return;
}
// if it has text content, return
if (hasTextContentChild(node)) {
if ((0, hasTextContentChild_1.hasTextContentChild)(node)) {
return;
}
// if it is not an icon button, return
if (!hasProp(openingElement.attributes, "icon") && !hasProp(openingElement.attributes, "expandIcon")) {
if (!(0, jsx_ast_utils_1.hasProp)(openingElement.attributes, "icon") &&
!(0, jsx_ast_utils_1.hasProp)(openingElement.attributes, "expandIcon")) {
return;
}
// if it has a tooltip parent, return
if (hasToolTipParent(context)) {
if ((0, hasTooltipParent_1.hasToolTipParent)(context)) {
return;
}
// the button has an associated label
if (hasAssociatedLabelViaAriaLabelledBy(openingElement, context)) {
if ((0, labelUtils_1.hasAssociatedLabelViaAriaLabelledBy)(openingElement, context)) {
return;
}
const hasAccessibleLabelling = hasNonEmptyProp(openingElement.attributes, "title") || hasNonEmptyProp(openingElement.attributes, "aria-label");
const hasAccessibleLabelling = (0, hasNonEmptyProp_1.hasNonEmptyProp)(openingElement.attributes, "title") || (0, hasNonEmptyProp_1.hasNonEmptyProp)(openingElement.attributes, "aria-label");
// if it has no accessible name, report error
if (!hasAccessibleLabelling) {
context.report({
Expand All @@ -62,4 +62,5 @@ module.exports = {
}
};
}
};
});
exports.default = rule;
7 changes: 5 additions & 2 deletions dist/lib/rules/accordion-item-needs-header-and-panel.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
declare const _exports: import("eslint").Rule.RuleModule;
export = _exports;
import { TSESTree } from "@typescript-eslint/utils";
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"accordionItemOneHeaderOnePanel", [], {
JSXOpeningElement(node: TSESTree.JSXOpeningElement): void;
}>;
export default rule;
25 changes: 16 additions & 9 deletions dist/lib/rules/accordion-item-needs-header-and-panel.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
const rule = utils_1.ESLintUtils.RuleCreator.withoutDocs({
defaultOptions: [],
meta: {
messages: {
accordionItemOneHeaderOnePanel: "ensure AccordionItem has exactly one header and one panel"
},
type: "problem", // `problem`, `suggestion`, or `layout`
docs: {
description: "An AccordionItem needs exactly one header and one panel",
recommended: true,
recommended: "strict",
url: "https://www.w3.org/WAI/ARIA/apg/patterns/accordion/" // URL to the documentation page for this rule
},
fixable: null, // Or `code` or `whitespace`
schema: [] // Add a schema if the rule has options
},
create(context) {
return {
JSXOpeningElement(node) {
if (node.name.name !== "AccordionItem") {
if (node.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier && node.name.name !== "AccordionItem") {
return;
}
if (!(node.parent && node.parent.type === utils_1.AST_NODE_TYPES.JSXElement)) {
return;
}
const children = node.parent.children.filter(child => child.type === "JSXElement");
const hasOneHeader = children.filter(child => child.openingElement.name.name === "AccordionHeader").length === 1;
const hasOnePanel = children.filter(child => child.openingElement.name.name === "AccordionPanel").length === 1;
const hasOneHeader = children.filter(child => child.openingElement.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
child.openingElement.name.name === "AccordionHeader").length === 1;
const hasOnePanel = children.filter(child => child.openingElement.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
child.openingElement.name.name === "AccordionPanel").length === 1;
if (!hasOneHeader || !hasOnePanel || children.length !== 2) {
context.report({
node,
Expand All @@ -37,4 +43,5 @@ module.exports = {
}
};
}
};
});
exports.default = rule;
20 changes: 5 additions & 15 deletions dist/lib/rules/avatar-needs-name.d.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
export namespace meta {
namespace messages {
let missingAriaLabel: string;
}
let type: string;
namespace docs {
let description: string;
let recommended: boolean;
let url: string;
}
let schema: never[];
}
export function create(context: any): {
JSXOpeningElement(node: any): void;
};
import { TSESTree } from "@typescript-eslint/utils";
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"missingAriaLabel", [], {
JSXOpeningElement(node: TSESTree.JSXOpeningElement): void;
}>;
export default rule;
26 changes: 15 additions & 11 deletions dist/lib/rules/avatar-needs-name.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
"use strict";
const { hasNonEmptyProp } = require("../util/hasNonEmptyProp");
var elementType = require("jsx-ast-utils").elementType;
const { hasAssociatedLabelViaAriaLabelledBy } = require("../util/labelUtils");
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const jsx_ast_utils_1 = require("jsx-ast-utils");
const hasNonEmptyProp_1 = require("../util/hasNonEmptyProp");
const labelUtils_1 = require("../util/labelUtils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
const rule = utils_1.ESLintUtils.RuleCreator.withoutDocs({
defaultOptions: [],
meta: {
// possible error messages for the rule
messages: {
Expand All @@ -19,7 +22,7 @@ module.exports = {
docs: {
// DONE
description: "Accessibility: Avatar must have an accessible labelling: name, aria-label, aria-labelledby",
recommended: true,
recommended: "strict",
url: "https://www.w3.org/TR/html-aria/" // URL to the documentation page for this rule
},
schema: []
Expand All @@ -30,13 +33,13 @@ module.exports = {
// visitor functions for different types of nodes
JSXOpeningElement(node) {
// if it is not an Avatar, return
if (elementType(node) !== "Avatar") {
if ((0, jsx_ast_utils_1.elementType)(node) !== "Avatar") {
return;
}
// if the Avatar has a name, aria-label or aria-labelledby, return
if (hasNonEmptyProp(node.attributes, "name") ||
hasNonEmptyProp(node.attributes, "aria-label") ||
hasAssociatedLabelViaAriaLabelledBy(node, context)) {
if ((0, hasNonEmptyProp_1.hasNonEmptyProp)(node.attributes, "name") ||
(0, hasNonEmptyProp_1.hasNonEmptyProp)(node.attributes, "aria-label") ||
(0, labelUtils_1.hasAssociatedLabelViaAriaLabelledBy)(node, context)) {
return;
}
// no aria
Expand All @@ -47,4 +50,5 @@ module.exports = {
}
};
}
};
});
exports.default = rule;
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
declare const _exports: import("eslint").Rule.RuleModule;
export = _exports;
import { TSESTree } from "@typescript-eslint/utils";
declare const rule: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"noAriaDescribedbyAsLabel", [], {
JSXElement(node: TSESTree.JSXElement): void;
}>;
export default rule;
Loading

0 comments on commit f4cfee3

Please sign in to comment.