@arcaauth/eslint-plugin-jsx-a11y 6.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +17 -0
- package/.eslintrc +44 -0
- package/CHANGELOG.md +774 -0
- package/LICENSE.md +8 -0
- package/README.md +423 -0
- package/__mocks__/IdentifierMock.js +15 -0
- package/__mocks__/JSXAttributeMock.js +39 -0
- package/__mocks__/JSXElementMock.js +37 -0
- package/__mocks__/JSXExpressionContainerMock.js +15 -0
- package/__mocks__/JSXSpreadAttributeMock.js +18 -0
- package/__mocks__/JSXTextMock.js +17 -0
- package/__mocks__/LiteralMock.js +17 -0
- package/__mocks__/genInteractives.js +218 -0
- package/__tests__/__util__/axeMapping.js +6 -0
- package/__tests__/__util__/helpers/getESLintCoreRule.js +9 -0
- package/__tests__/__util__/helpers/parsers.js +186 -0
- package/__tests__/__util__/parserOptionsMapper.js +53 -0
- package/__tests__/__util__/ruleOptionsMapperFactory.js +33 -0
- package/__tests__/index-test.js +40 -0
- package/__tests__/src/rules/accessible-emoji-test.js +66 -0
- package/__tests__/src/rules/alt-text-test.js +291 -0
- package/__tests__/src/rules/anchor-ambiguous-text-test.js +117 -0
- package/__tests__/src/rules/anchor-has-content-test.js +54 -0
- package/__tests__/src/rules/anchor-is-valid-test.js +532 -0
- package/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js +95 -0
- package/__tests__/src/rules/aria-props-test.js +69 -0
- package/__tests__/src/rules/aria-proptypes-test.js +311 -0
- package/__tests__/src/rules/aria-role-test.js +118 -0
- package/__tests__/src/rules/aria-unsupported-elements-test.js +75 -0
- package/__tests__/src/rules/autocomplete-valid-test.js +77 -0
- package/__tests__/src/rules/click-events-have-key-events-test.js +77 -0
- package/__tests__/src/rules/control-has-associated-label-test.js +327 -0
- package/__tests__/src/rules/heading-has-content-test.js +85 -0
- package/__tests__/src/rules/html-has-lang-test.js +42 -0
- package/__tests__/src/rules/iframe-has-title-test.js +55 -0
- package/__tests__/src/rules/img-redundant-alt-test.js +137 -0
- package/__tests__/src/rules/interactive-supports-focus-test.js +267 -0
- package/__tests__/src/rules/label-has-associated-control-test.js +243 -0
- package/__tests__/src/rules/label-has-for-test.js +235 -0
- package/__tests__/src/rules/lang-test.js +59 -0
- package/__tests__/src/rules/media-has-caption-test.js +220 -0
- package/__tests__/src/rules/mouse-events-have-key-events-test.js +154 -0
- package/__tests__/src/rules/no-access-key-test.js +48 -0
- package/__tests__/src/rules/no-aria-hidden-on-focusable-test.js +44 -0
- package/__tests__/src/rules/no-autofocus-test.js +68 -0
- package/__tests__/src/rules/no-distracting-elements-test.js +51 -0
- package/__tests__/src/rules/no-interactive-element-to-noninteractive-role-test.js +405 -0
- package/__tests__/src/rules/no-noninteractive-element-interactions-test.js +502 -0
- package/__tests__/src/rules/no-noninteractive-element-to-interactive-role-test.js +500 -0
- package/__tests__/src/rules/no-noninteractive-tabindex-test.js +123 -0
- package/__tests__/src/rules/no-onchange-test.js +57 -0
- package/__tests__/src/rules/no-redundant-roles-test.js +98 -0
- package/__tests__/src/rules/no-static-element-interactions-test.js +501 -0
- package/__tests__/src/rules/prefer-tag-over-role-test.js +63 -0
- package/__tests__/src/rules/role-has-required-aria-props-test.js +134 -0
- package/__tests__/src/rules/role-supports-aria-props-test.js +570 -0
- package/__tests__/src/rules/scope-test.js +50 -0
- package/__tests__/src/rules/tabindex-no-positive-test.js +55 -0
- package/__tests__/src/util/attributesComparator-test.js +91 -0
- package/__tests__/src/util/getAccessibleChildText-test.js +174 -0
- package/__tests__/src/util/getComputedRole-test.js +71 -0
- package/__tests__/src/util/getElementType-test.js +154 -0
- package/__tests__/src/util/getExplicitRole-test.js +35 -0
- package/__tests__/src/util/getImplicitRole-test.js +25 -0
- package/__tests__/src/util/getSuggestion-test.js +33 -0
- package/__tests__/src/util/getTabIndex-test.js +85 -0
- package/__tests__/src/util/hasAccessibleChild-test.js +157 -0
- package/__tests__/src/util/implicitRoles/input-test.js +87 -0
- package/__tests__/src/util/implicitRoles/menu-test.js +20 -0
- package/__tests__/src/util/implicitRoles/menuitem-test.js +38 -0
- package/__tests__/src/util/isAbstractRole-test.js +51 -0
- package/__tests__/src/util/isContentEditable-test.js +52 -0
- package/__tests__/src/util/isDOMElement-test.js +30 -0
- package/__tests__/src/util/isDisabledElement-test.js +88 -0
- package/__tests__/src/util/isFocusable-test.js +111 -0
- package/__tests__/src/util/isInteractiveElement-test.js +104 -0
- package/__tests__/src/util/isInteractiveRole-test.js +59 -0
- package/__tests__/src/util/isNonInteractiveElement-test.js +97 -0
- package/__tests__/src/util/isNonInteractiveRole-test.js +59 -0
- package/__tests__/src/util/isNonLiteralProperty-test.js +52 -0
- package/__tests__/src/util/isSemanticRoleElement-test.js +72 -0
- package/__tests__/src/util/mayContainChildComponent-test.js +219 -0
- package/__tests__/src/util/mayHaveAccessibleLabel-test.js +256 -0
- package/__tests__/src/util/parserOptionsMapper-test.js +93 -0
- package/__tests__/src/util/schemas-test.js +35 -0
- package/docs/rules/accessible-emoji.md +30 -0
- package/docs/rules/alt-text.md +168 -0
- package/docs/rules/anchor-ambiguous-text.md +91 -0
- package/docs/rules/anchor-has-content.md +64 -0
- package/docs/rules/anchor-is-valid.md +270 -0
- package/docs/rules/aria-activedescendant-has-tabindex.md +52 -0
- package/docs/rules/aria-props.md +29 -0
- package/docs/rules/aria-proptypes.md +30 -0
- package/docs/rules/aria-role.md +51 -0
- package/docs/rules/aria-unsupported-elements.md +30 -0
- package/docs/rules/autocomplete-valid.md +49 -0
- package/docs/rules/click-events-have-key-events.md +28 -0
- package/docs/rules/control-has-associated-label.md +113 -0
- package/docs/rules/heading-has-content.md +67 -0
- package/docs/rules/html-has-lang.md +31 -0
- package/docs/rules/iframe-has-title.md +37 -0
- package/docs/rules/img-redundant-alt.md +48 -0
- package/docs/rules/interactive-supports-focus.md +156 -0
- package/docs/rules/label-has-associated-control.md +152 -0
- package/docs/rules/label-has-for.md +130 -0
- package/docs/rules/lang.md +31 -0
- package/docs/rules/media-has-caption.md +48 -0
- package/docs/rules/mouse-events-have-key-events.md +58 -0
- package/docs/rules/no-access-key.md +30 -0
- package/docs/rules/no-aria-hidden-on-focusable.md +37 -0
- package/docs/rules/no-autofocus.md +43 -0
- package/docs/rules/no-distracting-elements.md +41 -0
- package/docs/rules/no-interactive-element-to-noninteractive-role.md +73 -0
- package/docs/rules/no-noninteractive-element-interactions.md +145 -0
- package/docs/rules/no-noninteractive-element-to-interactive-role.md +76 -0
- package/docs/rules/no-noninteractive-tabindex.md +115 -0
- package/docs/rules/no-onchange.md +36 -0
- package/docs/rules/no-redundant-roles.md +46 -0
- package/docs/rules/no-static-element-interactions.md +114 -0
- package/docs/rules/prefer-tag-over-role.md +32 -0
- package/docs/rules/role-has-required-aria-props.md +31 -0
- package/docs/rules/role-supports-aria-props.md +39 -0
- package/docs/rules/scope.md +30 -0
- package/docs/rules/tabindex-no-positive.md +32 -0
- package/lib/configs/flat-config-base.js +11 -0
- package/lib/configs/legacy-config-base.js +9 -0
- package/lib/index.js +209 -0
- package/lib/rules/accessible-emoji.js +63 -0
- package/lib/rules/alt-text.js +218 -0
- package/lib/rules/anchor-ambiguous-text.js +64 -0
- package/lib/rules/anchor-has-content.js +60 -0
- package/lib/rules/anchor-is-valid.js +122 -0
- package/lib/rules/aria-activedescendant-has-tabindex.js +66 -0
- package/lib/rules/aria-props.js +59 -0
- package/lib/rules/aria-proptypes.js +114 -0
- package/lib/rules/aria-role.js +89 -0
- package/lib/rules/aria-unsupported-elements.js +64 -0
- package/lib/rules/autocomplete-valid.js +67 -0
- package/lib/rules/click-events-have-key-events.js +68 -0
- package/lib/rules/control-has-associated-label.js +103 -0
- package/lib/rules/heading-has-content.js +61 -0
- package/lib/rules/html-has-lang.js +50 -0
- package/lib/rules/iframe-has-title.js +50 -0
- package/lib/rules/img-redundant-alt.js +88 -0
- package/lib/rules/interactive-supports-focus.js +87 -0
- package/lib/rules/label-has-associated-control.js +127 -0
- package/lib/rules/label-has-for.js +150 -0
- package/lib/rules/lang.js +68 -0
- package/lib/rules/media-has-caption.js +96 -0
- package/lib/rules/mouse-events-have-key-events.js +94 -0
- package/lib/rules/no-access-key.js +43 -0
- package/lib/rules/no-aria-hidden-on-focusable.js +47 -0
- package/lib/rules/no-autofocus.js +62 -0
- package/lib/rules/no-distracting-elements.js +54 -0
- package/lib/rules/no-interactive-element-to-noninteractive-role.js +81 -0
- package/lib/rules/no-noninteractive-element-interactions.js +95 -0
- package/lib/rules/no-noninteractive-element-to-interactive-role.js +80 -0
- package/lib/rules/no-noninteractive-tabindex.js +109 -0
- package/lib/rules/no-onchange.js +52 -0
- package/lib/rules/no-redundant-roles.js +86 -0
- package/lib/rules/no-static-element-interactions.js +102 -0
- package/lib/rules/prefer-tag-over-role.js +75 -0
- package/lib/rules/role-has-required-aria-props.js +88 -0
- package/lib/rules/role-supports-aria-props.js +78 -0
- package/lib/rules/scope.js +58 -0
- package/lib/rules/tabindex-no-positive.js +53 -0
- package/lib/util/attributesComparator.js +34 -0
- package/lib/util/getAccessibleChildText.js +55 -0
- package/lib/util/getComputedRole.js +19 -0
- package/lib/util/getElementType.js +30 -0
- package/lib/util/getExplicitRole.js +27 -0
- package/lib/util/getImplicitRole.js +24 -0
- package/lib/util/getSuggestion.js +32 -0
- package/lib/util/getTabIndex.js +34 -0
- package/lib/util/hasAccessibleChild.js +30 -0
- package/lib/util/implicitRoles/a.js +17 -0
- package/lib/util/implicitRoles/area.js +17 -0
- package/lib/util/implicitRoles/article.js +13 -0
- package/lib/util/implicitRoles/aside.js +13 -0
- package/lib/util/implicitRoles/body.js +13 -0
- package/lib/util/implicitRoles/button.js +13 -0
- package/lib/util/implicitRoles/datalist.js +13 -0
- package/lib/util/implicitRoles/details.js +13 -0
- package/lib/util/implicitRoles/dialog.js +13 -0
- package/lib/util/implicitRoles/form.js +13 -0
- package/lib/util/implicitRoles/h1.js +13 -0
- package/lib/util/implicitRoles/h2.js +13 -0
- package/lib/util/implicitRoles/h3.js +13 -0
- package/lib/util/implicitRoles/h4.js +13 -0
- package/lib/util/implicitRoles/h5.js +13 -0
- package/lib/util/implicitRoles/h6.js +13 -0
- package/lib/util/implicitRoles/hr.js +13 -0
- package/lib/util/implicitRoles/img.js +31 -0
- package/lib/util/implicitRoles/index.js +82 -0
- package/lib/util/implicitRoles/input.js +38 -0
- package/lib/util/implicitRoles/li.js +13 -0
- package/lib/util/implicitRoles/link.js +17 -0
- package/lib/util/implicitRoles/menu.js +19 -0
- package/lib/util/implicitRoles/menuitem.js +28 -0
- package/lib/util/implicitRoles/meter.js +13 -0
- package/lib/util/implicitRoles/nav.js +13 -0
- package/lib/util/implicitRoles/ol.js +13 -0
- package/lib/util/implicitRoles/option.js +13 -0
- package/lib/util/implicitRoles/output.js +13 -0
- package/lib/util/implicitRoles/progress.js +13 -0
- package/lib/util/implicitRoles/section.js +13 -0
- package/lib/util/implicitRoles/select.js +13 -0
- package/lib/util/implicitRoles/tbody.js +13 -0
- package/lib/util/implicitRoles/textarea.js +13 -0
- package/lib/util/implicitRoles/tfoot.js +13 -0
- package/lib/util/implicitRoles/thead.js +13 -0
- package/lib/util/implicitRoles/ul.js +13 -0
- package/lib/util/isAbstractRole.js +23 -0
- package/lib/util/isContentEditable.js +13 -0
- package/lib/util/isDOMElement.js +15 -0
- package/lib/util/isDisabledElement.js +23 -0
- package/lib/util/isFocusable.js +23 -0
- package/lib/util/isHiddenFromScreenReader.js +26 -0
- package/lib/util/isInteractiveElement.js +116 -0
- package/lib/util/isInteractiveRole.js +54 -0
- package/lib/util/isNonInteractiveElement.js +131 -0
- package/lib/util/isNonInteractiveRole.js +55 -0
- package/lib/util/isNonLiteralProperty.js +29 -0
- package/lib/util/isPresentationRole.js +13 -0
- package/lib/util/isSemanticRoleElement.js +54 -0
- package/lib/util/mayContainChildComponent.js +50 -0
- package/lib/util/mayHaveAccessibleLabel.js +95 -0
- package/lib/util/schemas.js +52 -0
- package/package.json +120 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _ariaQuery = require("aria-query");
|
|
8
|
+
var _jsxAstUtils = require("jsx-ast-utils");
|
|
9
|
+
var _arrayIncludes = _interopRequireDefault(require("array-includes"));
|
|
10
|
+
var _hasown = _interopRequireDefault(require("hasown"));
|
|
11
|
+
var _getElementType = _interopRequireDefault(require("../util/getElementType"));
|
|
12
|
+
var _isInteractiveElement = _interopRequireDefault(require("../util/isInteractiveElement"));
|
|
13
|
+
var _isNonInteractiveRole = _interopRequireDefault(require("../util/isNonInteractiveRole"));
|
|
14
|
+
var _isPresentationRole = _interopRequireDefault(require("../util/isPresentationRole"));
|
|
15
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
16
|
+
/**
|
|
17
|
+
* @fileoverview Disallow inherently interactive elements to be assigned
|
|
18
|
+
* non-interactive roles.
|
|
19
|
+
* @author Jesse Beach
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// ----------------------------------------------------------------------------
|
|
24
|
+
// Rule Definition
|
|
25
|
+
// ----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
var errorMessage = 'Interactive elements should not be assigned non-interactive roles.';
|
|
28
|
+
var _default = exports["default"] = {
|
|
29
|
+
meta: {
|
|
30
|
+
docs: {
|
|
31
|
+
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-interactive-element-to-noninteractive-role.md',
|
|
32
|
+
description: 'Interactive elements should not be assigned non-interactive roles.'
|
|
33
|
+
},
|
|
34
|
+
schema: [{
|
|
35
|
+
type: 'object',
|
|
36
|
+
additionalProperties: {
|
|
37
|
+
type: 'array',
|
|
38
|
+
items: {
|
|
39
|
+
type: 'string'
|
|
40
|
+
},
|
|
41
|
+
uniqueItems: true
|
|
42
|
+
}
|
|
43
|
+
}]
|
|
44
|
+
},
|
|
45
|
+
create: function create(context) {
|
|
46
|
+
var options = context.options;
|
|
47
|
+
var elementType = (0, _getElementType["default"])(context);
|
|
48
|
+
return {
|
|
49
|
+
JSXAttribute: function JSXAttribute(attribute) {
|
|
50
|
+
var attributeName = (0, _jsxAstUtils.propName)(attribute);
|
|
51
|
+
// $FlowFixMe: [TODO] Mark propName as a JSXIdentifier, not a string.
|
|
52
|
+
if (attributeName !== 'role') {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
var node = attribute.parent;
|
|
56
|
+
var attributes = node.attributes;
|
|
57
|
+
var type = elementType(node);
|
|
58
|
+
var role = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'role'));
|
|
59
|
+
if (!_ariaQuery.dom.has(type)) {
|
|
60
|
+
// Do not test higher level JSX components, as we do not know what
|
|
61
|
+
// low-level DOM element this maps to.
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Allow overrides from rule configuration for specific elements and
|
|
65
|
+
// roles.
|
|
66
|
+
var allowedRoles = options[0] || {};
|
|
67
|
+
if ((0, _hasown["default"])(allowedRoles, type) && (0, _arrayIncludes["default"])(allowedRoles[type], role)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if ((0, _isInteractiveElement["default"])(type, attributes) && ((0, _isNonInteractiveRole["default"])(type, attributes) || (0, _isPresentationRole["default"])(type, attributes))) {
|
|
71
|
+
// Visible, non-interactive elements should not have an interactive handler.
|
|
72
|
+
context.report({
|
|
73
|
+
node: attribute,
|
|
74
|
+
message: errorMessage
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _ariaQuery = require("aria-query");
|
|
8
|
+
var _jsxAstUtils = require("jsx-ast-utils");
|
|
9
|
+
var _arrayIncludes = _interopRequireDefault(require("array-includes"));
|
|
10
|
+
var _hasown = _interopRequireDefault(require("hasown"));
|
|
11
|
+
var _schemas = require("../util/schemas");
|
|
12
|
+
var _getElementType = _interopRequireDefault(require("../util/getElementType"));
|
|
13
|
+
var _isAbstractRole = _interopRequireDefault(require("../util/isAbstractRole"));
|
|
14
|
+
var _isContentEditable = _interopRequireDefault(require("../util/isContentEditable"));
|
|
15
|
+
var _isHiddenFromScreenReader = _interopRequireDefault(require("../util/isHiddenFromScreenReader"));
|
|
16
|
+
var _isInteractiveElement = _interopRequireDefault(require("../util/isInteractiveElement"));
|
|
17
|
+
var _isInteractiveRole = _interopRequireDefault(require("../util/isInteractiveRole"));
|
|
18
|
+
var _isNonInteractiveElement = _interopRequireDefault(require("../util/isNonInteractiveElement"));
|
|
19
|
+
var _isNonInteractiveRole = _interopRequireDefault(require("../util/isNonInteractiveRole"));
|
|
20
|
+
var _isPresentationRole = _interopRequireDefault(require("../util/isPresentationRole"));
|
|
21
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
22
|
+
/**
|
|
23
|
+
* @fileoverview Enforce non-interactive elements have no interactive handlers.
|
|
24
|
+
* @author Jese Beach
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
// ----------------------------------------------------------------------------
|
|
28
|
+
// Rule Definition
|
|
29
|
+
// ----------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
var errorMessage = 'Non-interactive elements should not be assigned mouse or keyboard event listeners.';
|
|
32
|
+
var defaultInteractiveProps = [].concat(_jsxAstUtils.eventHandlersByType.focus, _jsxAstUtils.eventHandlersByType.image, _jsxAstUtils.eventHandlersByType.keyboard, _jsxAstUtils.eventHandlersByType.mouse);
|
|
33
|
+
var schema = (0, _schemas.generateObjSchema)({
|
|
34
|
+
handlers: _schemas.arraySchema
|
|
35
|
+
});
|
|
36
|
+
var _default = exports["default"] = {
|
|
37
|
+
meta: {
|
|
38
|
+
docs: {
|
|
39
|
+
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-noninteractive-element-interactions.md',
|
|
40
|
+
description: 'Non-interactive elements should not be assigned mouse or keyboard event listeners.'
|
|
41
|
+
},
|
|
42
|
+
schema: [schema]
|
|
43
|
+
},
|
|
44
|
+
create: function create(context) {
|
|
45
|
+
var options = context.options;
|
|
46
|
+
var elementType = (0, _getElementType["default"])(context);
|
|
47
|
+
return {
|
|
48
|
+
JSXOpeningElement: function (_JSXOpeningElement) {
|
|
49
|
+
function JSXOpeningElement(_x) {
|
|
50
|
+
return _JSXOpeningElement.apply(this, arguments);
|
|
51
|
+
}
|
|
52
|
+
JSXOpeningElement.toString = function () {
|
|
53
|
+
return _JSXOpeningElement.toString();
|
|
54
|
+
};
|
|
55
|
+
return JSXOpeningElement;
|
|
56
|
+
}(function (node) {
|
|
57
|
+
var attributes = node.attributes;
|
|
58
|
+
var type = elementType(node);
|
|
59
|
+
var config = options[0] || {};
|
|
60
|
+
var interactiveProps = config.handlers || defaultInteractiveProps;
|
|
61
|
+
// Allow overrides from rule configuration for specific elements and roles.
|
|
62
|
+
if ((0, _hasown["default"])(config, type)) {
|
|
63
|
+
attributes = attributes.filter(function (attr) {
|
|
64
|
+
return attr.type !== 'JSXSpreadAttribute' && !(0, _arrayIncludes["default"])(config[type], (0, _jsxAstUtils.propName)(attr));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
var hasInteractiveProps = interactiveProps.some(function (prop) {
|
|
68
|
+
return (0, _jsxAstUtils.hasProp)(attributes, prop) && (0, _jsxAstUtils.getPropValue)((0, _jsxAstUtils.getProp)(attributes, prop)) != null;
|
|
69
|
+
});
|
|
70
|
+
if (!_ariaQuery.dom.has(type)) {
|
|
71
|
+
// Do not test higher level JSX components, as we do not know what
|
|
72
|
+
// low-level DOM element this maps to.
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!hasInteractiveProps || (0, _isContentEditable["default"])(type, attributes) || (0, _isHiddenFromScreenReader["default"])(type, attributes) || (0, _isPresentationRole["default"])(type, attributes)) {
|
|
76
|
+
// Presentation is an intentional signal from the author that this
|
|
77
|
+
// element is not meant to be perceivable. For example, a click screen
|
|
78
|
+
// to close a dialog .
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if ((0, _isInteractiveElement["default"])(type, attributes) || (0, _isInteractiveRole["default"])(type, attributes) || !(0, _isNonInteractiveElement["default"])(type, attributes) && !(0, _isNonInteractiveRole["default"])(type, attributes) || (0, _isAbstractRole["default"])(type, attributes)) {
|
|
82
|
+
// This rule has no opinion about abtract roles.
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Visible, non-interactive elements should not have an interactive handler.
|
|
87
|
+
context.report({
|
|
88
|
+
node,
|
|
89
|
+
message: errorMessage
|
|
90
|
+
});
|
|
91
|
+
})
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _ariaQuery = require("aria-query");
|
|
8
|
+
var _jsxAstUtils = require("jsx-ast-utils");
|
|
9
|
+
var _arrayIncludes = _interopRequireDefault(require("array-includes"));
|
|
10
|
+
var _hasown = _interopRequireDefault(require("hasown"));
|
|
11
|
+
var _getElementType = _interopRequireDefault(require("../util/getElementType"));
|
|
12
|
+
var _getExplicitRole = _interopRequireDefault(require("../util/getExplicitRole"));
|
|
13
|
+
var _isNonInteractiveElement = _interopRequireDefault(require("../util/isNonInteractiveElement"));
|
|
14
|
+
var _isInteractiveRole = _interopRequireDefault(require("../util/isInteractiveRole"));
|
|
15
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
16
|
+
/**
|
|
17
|
+
* @fileoverview Disallow inherently non-interactive elements to be assigned
|
|
18
|
+
* interactive roles.
|
|
19
|
+
* @author Jesse Beach
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// ----------------------------------------------------------------------------
|
|
24
|
+
// Rule Definition
|
|
25
|
+
// ----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
var errorMessage = 'Non-interactive elements should not be assigned interactive roles.';
|
|
28
|
+
var _default = exports["default"] = {
|
|
29
|
+
meta: {
|
|
30
|
+
docs: {
|
|
31
|
+
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-noninteractive-element-to-interactive-role.md',
|
|
32
|
+
description: 'Non-interactive elements should not be assigned interactive roles.'
|
|
33
|
+
},
|
|
34
|
+
schema: [{
|
|
35
|
+
type: 'object',
|
|
36
|
+
additionalProperties: {
|
|
37
|
+
type: 'array',
|
|
38
|
+
items: {
|
|
39
|
+
type: 'string'
|
|
40
|
+
},
|
|
41
|
+
uniqueItems: true
|
|
42
|
+
}
|
|
43
|
+
}]
|
|
44
|
+
},
|
|
45
|
+
create: function create(context) {
|
|
46
|
+
var options = context.options;
|
|
47
|
+
var elementType = (0, _getElementType["default"])(context);
|
|
48
|
+
return {
|
|
49
|
+
JSXAttribute: function JSXAttribute(attribute) {
|
|
50
|
+
var attributeName = (0, _jsxAstUtils.propName)(attribute);
|
|
51
|
+
// $FlowFixMe: [TODO] Mark propName as a JSXIdentifier, not a string.
|
|
52
|
+
if (attributeName !== 'role') {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
var node = attribute.parent;
|
|
56
|
+
var attributes = node.attributes;
|
|
57
|
+
var type = elementType(node);
|
|
58
|
+
var role = (0, _getExplicitRole["default"])(type, node.attributes);
|
|
59
|
+
if (!_ariaQuery.dom.has(type)) {
|
|
60
|
+
// Do not test higher level JSX components, as we do not know what
|
|
61
|
+
// low-level DOM element this maps to.
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Allow overrides from rule configuration for specific elements and
|
|
65
|
+
// roles.
|
|
66
|
+
var allowedRoles = options[0] || {};
|
|
67
|
+
if ((0, _hasown["default"])(allowedRoles, type) && (0, _arrayIncludes["default"])(allowedRoles[type], role)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if ((0, _isNonInteractiveElement["default"])(type, attributes) && (0, _isInteractiveRole["default"])(type, attributes)) {
|
|
71
|
+
context.report({
|
|
72
|
+
node: attribute,
|
|
73
|
+
message: errorMessage
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _ariaQuery = require("aria-query");
|
|
8
|
+
var _jsxAstUtils = require("jsx-ast-utils");
|
|
9
|
+
var _arrayIncludes = _interopRequireDefault(require("array-includes"));
|
|
10
|
+
var _getElementType = _interopRequireDefault(require("../util/getElementType"));
|
|
11
|
+
var _isInteractiveElement = _interopRequireDefault(require("../util/isInteractiveElement"));
|
|
12
|
+
var _isInteractiveRole = _interopRequireDefault(require("../util/isInteractiveRole"));
|
|
13
|
+
var _isNonLiteralProperty = _interopRequireDefault(require("../util/isNonLiteralProperty"));
|
|
14
|
+
var _schemas = require("../util/schemas");
|
|
15
|
+
var _getTabIndex = _interopRequireDefault(require("../util/getTabIndex"));
|
|
16
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
17
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
18
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
19
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
20
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
21
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
22
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /**
|
|
23
|
+
* @fileoverview Disallow tabindex on static and noninteractive elements
|
|
24
|
+
* @author jessebeach
|
|
25
|
+
*
|
|
26
|
+
*/ // ----------------------------------------------------------------------------
|
|
27
|
+
// Rule Definition
|
|
28
|
+
// ----------------------------------------------------------------------------
|
|
29
|
+
var errorMessage = '`tabIndex` should only be declared on interactive elements.';
|
|
30
|
+
var schema = (0, _schemas.generateObjSchema)({
|
|
31
|
+
roles: _objectSpread(_objectSpread({}, _schemas.arraySchema), {}, {
|
|
32
|
+
description: 'An array of ARIA roles'
|
|
33
|
+
}),
|
|
34
|
+
tags: _objectSpread(_objectSpread({}, _schemas.arraySchema), {}, {
|
|
35
|
+
description: 'An array of HTML tag names'
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
var _default = exports["default"] = {
|
|
39
|
+
meta: {
|
|
40
|
+
docs: {
|
|
41
|
+
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-noninteractive-tabindex.md',
|
|
42
|
+
description: '`tabIndex` should only be declared on interactive elements.'
|
|
43
|
+
},
|
|
44
|
+
schema: [schema]
|
|
45
|
+
},
|
|
46
|
+
create: function create(context) {
|
|
47
|
+
var options = context.options;
|
|
48
|
+
var elementType = (0, _getElementType["default"])(context);
|
|
49
|
+
return {
|
|
50
|
+
JSXOpeningElement: function (_JSXOpeningElement) {
|
|
51
|
+
function JSXOpeningElement(_x) {
|
|
52
|
+
return _JSXOpeningElement.apply(this, arguments);
|
|
53
|
+
}
|
|
54
|
+
JSXOpeningElement.toString = function () {
|
|
55
|
+
return _JSXOpeningElement.toString();
|
|
56
|
+
};
|
|
57
|
+
return JSXOpeningElement;
|
|
58
|
+
}(function (node) {
|
|
59
|
+
var type = elementType(node);
|
|
60
|
+
var attributes = node.attributes;
|
|
61
|
+
var tabIndexProp = (0, _jsxAstUtils.getProp)(attributes, 'tabIndex');
|
|
62
|
+
var tabIndex = (0, _getTabIndex["default"])(tabIndexProp);
|
|
63
|
+
// Early return;
|
|
64
|
+
if (typeof tabIndex === 'undefined') {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
var role = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.attributes, 'role'));
|
|
68
|
+
if (!_ariaQuery.dom.has(type)) {
|
|
69
|
+
// Do not test higher level JSX components, as we do not know what
|
|
70
|
+
// low-level DOM element this maps to.
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Allow for configuration overrides.
|
|
74
|
+
var _ref = options[0] || {},
|
|
75
|
+
tags = _ref.tags,
|
|
76
|
+
roles = _ref.roles,
|
|
77
|
+
allowExpressionValues = _ref.allowExpressionValues;
|
|
78
|
+
if (tags && (0, _arrayIncludes["default"])(tags, type)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (roles && (0, _arrayIncludes["default"])(roles, role)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (allowExpressionValues === true && (0, _isNonLiteralProperty["default"])(attributes, 'role')) {
|
|
85
|
+
// Special case if role is assigned using ternary with literals on both side
|
|
86
|
+
var roleProp = (0, _jsxAstUtils.getProp)(attributes, 'role');
|
|
87
|
+
if (roleProp && roleProp.type === 'JSXAttribute' && roleProp.value.type === 'JSXExpressionContainer') {
|
|
88
|
+
if (roleProp.value.expression.type === 'ConditionalExpression') {
|
|
89
|
+
if (roleProp.value.expression.consequent.type === 'Literal' && roleProp.value.expression.alternate.type === 'Literal') {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if ((0, _isInteractiveElement["default"])(type, attributes) || (0, _isInteractiveRole["default"])(type, attributes)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (tabIndex >= 0) {
|
|
100
|
+
context.report({
|
|
101
|
+
node: tabIndexProp,
|
|
102
|
+
message: errorMessage
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _jsxAstUtils = require("jsx-ast-utils");
|
|
8
|
+
var _schemas = require("../util/schemas");
|
|
9
|
+
var _getElementType = _interopRequireDefault(require("../util/getElementType"));
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
11
|
+
/**
|
|
12
|
+
* @fileoverview Enforce usage of onBlur over onChange for accessibility.
|
|
13
|
+
* @author Ethan Cohen
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// ----------------------------------------------------------------------------
|
|
17
|
+
// Rule Definition
|
|
18
|
+
// ----------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
var errorMessage = 'onBlur must be used instead of onchange, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.';
|
|
21
|
+
var applicableTypes = ['select', 'option'];
|
|
22
|
+
var schema = (0, _schemas.generateObjSchema)();
|
|
23
|
+
var _default = exports["default"] = {
|
|
24
|
+
meta: {
|
|
25
|
+
docs: {
|
|
26
|
+
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-onchange.md',
|
|
27
|
+
description: 'Enforce usage of `onBlur` over `onChange` on select menus for accessibility.'
|
|
28
|
+
},
|
|
29
|
+
deprecated: true,
|
|
30
|
+
schema: [schema]
|
|
31
|
+
},
|
|
32
|
+
create: function create(context) {
|
|
33
|
+
var elementType = (0, _getElementType["default"])(context);
|
|
34
|
+
return {
|
|
35
|
+
JSXOpeningElement: function JSXOpeningElement(node) {
|
|
36
|
+
var nodeType = elementType(node);
|
|
37
|
+
if (applicableTypes.indexOf(nodeType) === -1) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
var onChange = (0, _jsxAstUtils.getProp)(node.attributes, 'onChange');
|
|
41
|
+
var hasOnBlur = (0, _jsxAstUtils.getProp)(node.attributes, 'onBlur') !== undefined;
|
|
42
|
+
if (onChange && !hasOnBlur) {
|
|
43
|
+
context.report({
|
|
44
|
+
node,
|
|
45
|
+
message: errorMessage
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _arrayIncludes = _interopRequireDefault(require("array-includes"));
|
|
8
|
+
var _hasown = _interopRequireDefault(require("hasown"));
|
|
9
|
+
var _getElementType = _interopRequireDefault(require("../util/getElementType"));
|
|
10
|
+
var _getExplicitRole = _interopRequireDefault(require("../util/getExplicitRole"));
|
|
11
|
+
var _getImplicitRole = _interopRequireDefault(require("../util/getImplicitRole"));
|
|
12
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
13
|
+
/**
|
|
14
|
+
* @fileoverview Enforce explicit role property is not the
|
|
15
|
+
* same as implicit/default role property on element.
|
|
16
|
+
* @author Ethan Cohen <@evcohen>
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// ----------------------------------------------------------------------------
|
|
21
|
+
// Rule Definition
|
|
22
|
+
// ----------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
var errorMessage = function errorMessage(element, implicitRole) {
|
|
25
|
+
return "The element ".concat(element, " has an implicit role of ").concat(implicitRole, ". Defining this explicitly is redundant and should be avoided.");
|
|
26
|
+
};
|
|
27
|
+
var DEFAULT_ROLE_EXCEPTIONS = {
|
|
28
|
+
nav: ['navigation']
|
|
29
|
+
};
|
|
30
|
+
var _default = exports["default"] = {
|
|
31
|
+
meta: {
|
|
32
|
+
docs: {
|
|
33
|
+
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-redundant-roles.md',
|
|
34
|
+
description: 'Enforce explicit role property is not the same as implicit/default role property on element.'
|
|
35
|
+
},
|
|
36
|
+
schema: [{
|
|
37
|
+
type: 'object',
|
|
38
|
+
additionalProperties: {
|
|
39
|
+
type: 'array',
|
|
40
|
+
items: {
|
|
41
|
+
type: 'string'
|
|
42
|
+
},
|
|
43
|
+
uniqueItems: true
|
|
44
|
+
}
|
|
45
|
+
}]
|
|
46
|
+
},
|
|
47
|
+
create: function create(context) {
|
|
48
|
+
var options = context.options;
|
|
49
|
+
var elementType = (0, _getElementType["default"])(context);
|
|
50
|
+
return {
|
|
51
|
+
JSXOpeningElement: function (_JSXOpeningElement) {
|
|
52
|
+
function JSXOpeningElement(_x) {
|
|
53
|
+
return _JSXOpeningElement.apply(this, arguments);
|
|
54
|
+
}
|
|
55
|
+
JSXOpeningElement.toString = function () {
|
|
56
|
+
return _JSXOpeningElement.toString();
|
|
57
|
+
};
|
|
58
|
+
return JSXOpeningElement;
|
|
59
|
+
}(function (node) {
|
|
60
|
+
var type = elementType(node);
|
|
61
|
+
var implicitRole = (0, _getImplicitRole["default"])(type, node.attributes);
|
|
62
|
+
var explicitRole = (0, _getExplicitRole["default"])(type, node.attributes);
|
|
63
|
+
if (!implicitRole || !explicitRole) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (implicitRole === explicitRole) {
|
|
67
|
+
var allowedRedundantRoles = options[0] || {};
|
|
68
|
+
var redundantRolesForElement;
|
|
69
|
+
if ((0, _hasown["default"])(allowedRedundantRoles, type)) {
|
|
70
|
+
redundantRolesForElement = allowedRedundantRoles[type];
|
|
71
|
+
} else {
|
|
72
|
+
redundantRolesForElement = DEFAULT_ROLE_EXCEPTIONS[type] || [];
|
|
73
|
+
}
|
|
74
|
+
if ((0, _arrayIncludes["default"])(redundantRolesForElement, implicitRole)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
context.report({
|
|
78
|
+
node,
|
|
79
|
+
message: errorMessage(type, implicitRole.toLowerCase())
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _ariaQuery = require("aria-query");
|
|
8
|
+
var _jsxAstUtils = require("jsx-ast-utils");
|
|
9
|
+
var _schemas = require("../util/schemas");
|
|
10
|
+
var _getElementType = _interopRequireDefault(require("../util/getElementType"));
|
|
11
|
+
var _isAbstractRole = _interopRequireDefault(require("../util/isAbstractRole"));
|
|
12
|
+
var _isHiddenFromScreenReader = _interopRequireDefault(require("../util/isHiddenFromScreenReader"));
|
|
13
|
+
var _isInteractiveElement = _interopRequireDefault(require("../util/isInteractiveElement"));
|
|
14
|
+
var _isInteractiveRole = _interopRequireDefault(require("../util/isInteractiveRole"));
|
|
15
|
+
var _isNonInteractiveElement = _interopRequireDefault(require("../util/isNonInteractiveElement"));
|
|
16
|
+
var _isNonInteractiveRole = _interopRequireDefault(require("../util/isNonInteractiveRole"));
|
|
17
|
+
var _isNonLiteralProperty = _interopRequireDefault(require("../util/isNonLiteralProperty"));
|
|
18
|
+
var _isPresentationRole = _interopRequireDefault(require("../util/isPresentationRole"));
|
|
19
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
20
|
+
/**
|
|
21
|
+
* @fileoverview Enforce static elements have no interactive handlers.
|
|
22
|
+
* @author Ethan Cohen
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// ----------------------------------------------------------------------------
|
|
27
|
+
// Rule Definition
|
|
28
|
+
// ----------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
var errorMessage = 'Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element.';
|
|
31
|
+
var defaultInteractiveProps = [].concat(_jsxAstUtils.eventHandlersByType.focus, _jsxAstUtils.eventHandlersByType.keyboard, _jsxAstUtils.eventHandlersByType.mouse);
|
|
32
|
+
var schema = (0, _schemas.generateObjSchema)({
|
|
33
|
+
handlers: _schemas.arraySchema
|
|
34
|
+
});
|
|
35
|
+
var _default = exports["default"] = {
|
|
36
|
+
meta: {
|
|
37
|
+
docs: {
|
|
38
|
+
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-static-element-interactions.md',
|
|
39
|
+
description: 'Enforce that non-interactive, visible elements (such as `<div>`) that have click handlers use the role attribute.'
|
|
40
|
+
},
|
|
41
|
+
schema: [schema]
|
|
42
|
+
},
|
|
43
|
+
create: function create(context) {
|
|
44
|
+
var options = context.options;
|
|
45
|
+
var elementType = (0, _getElementType["default"])(context);
|
|
46
|
+
return {
|
|
47
|
+
JSXOpeningElement: function (_JSXOpeningElement) {
|
|
48
|
+
function JSXOpeningElement(_x) {
|
|
49
|
+
return _JSXOpeningElement.apply(this, arguments);
|
|
50
|
+
}
|
|
51
|
+
JSXOpeningElement.toString = function () {
|
|
52
|
+
return _JSXOpeningElement.toString();
|
|
53
|
+
};
|
|
54
|
+
return JSXOpeningElement;
|
|
55
|
+
}(function (node) {
|
|
56
|
+
var attributes = node.attributes;
|
|
57
|
+
var type = elementType(node);
|
|
58
|
+
var _ref = options[0] || {},
|
|
59
|
+
allowExpressionValues = _ref.allowExpressionValues,
|
|
60
|
+
_ref$handlers = _ref.handlers,
|
|
61
|
+
handlers = _ref$handlers === void 0 ? defaultInteractiveProps : _ref$handlers;
|
|
62
|
+
var hasInteractiveProps = handlers.some(function (prop) {
|
|
63
|
+
return (0, _jsxAstUtils.hasProp)(attributes, prop) && (0, _jsxAstUtils.getPropValue)((0, _jsxAstUtils.getProp)(attributes, prop)) != null;
|
|
64
|
+
});
|
|
65
|
+
if (!_ariaQuery.dom.has(type)) {
|
|
66
|
+
// Do not test higher level JSX components, as we do not know what
|
|
67
|
+
// low-level DOM element this maps to.
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!hasInteractiveProps || (0, _isHiddenFromScreenReader["default"])(type, attributes) || (0, _isPresentationRole["default"])(type, attributes)) {
|
|
71
|
+
// Presentation is an intentional signal from the author that this
|
|
72
|
+
// element is not meant to be perceivable. For example, a click screen
|
|
73
|
+
// to close a dialog .
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if ((0, _isInteractiveElement["default"])(type, attributes) || (0, _isInteractiveRole["default"])(type, attributes) || (0, _isNonInteractiveElement["default"])(type, attributes) || (0, _isNonInteractiveRole["default"])(type, attributes) || (0, _isAbstractRole["default"])(type, attributes)) {
|
|
77
|
+
// This rule has no opinion about abstract roles.
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (allowExpressionValues === true && (0, _isNonLiteralProperty["default"])(attributes, 'role')) {
|
|
81
|
+
// Special case if role is assigned using ternary with literals on both side
|
|
82
|
+
var roleProp = (0, _jsxAstUtils.getProp)(attributes, 'role');
|
|
83
|
+
if (roleProp && roleProp.type === 'JSXAttribute' && roleProp.value.type === 'JSXExpressionContainer') {
|
|
84
|
+
if (roleProp.value.expression.type === 'ConditionalExpression') {
|
|
85
|
+
if (roleProp.value.expression.consequent.type === 'Literal' && roleProp.value.expression.alternate.type === 'Literal') {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Visible, non-interactive elements should not have an interactive handler.
|
|
94
|
+
context.report({
|
|
95
|
+
node,
|
|
96
|
+
message: errorMessage
|
|
97
|
+
});
|
|
98
|
+
})
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
module.exports = exports.default;
|