@elastic/eslint-plugin-eui 2.3.0 → 2.5.0
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/README.md +18 -3
- package/lib/cjs/index.js +19 -18
- package/lib/cjs/rules/a11y/accessible_interactive_element.d.ts +3 -0
- package/lib/cjs/rules/a11y/accessible_interactive_element.d.ts.map +1 -0
- package/lib/cjs/rules/a11y/accessible_interactive_element.js +51 -0
- package/lib/cjs/rules/a11y/callout_announce_on_mount.d.ts +3 -0
- package/lib/cjs/rules/a11y/callout_announce_on_mount.d.ts.map +1 -0
- package/lib/cjs/rules/a11y/callout_announce_on_mount.js +56 -0
- package/lib/cjs/rules/a11y/consistent_is_invalid_props.d.ts.map +1 -1
- package/lib/cjs/rules/a11y/consistent_is_invalid_props.js +7 -18
- package/lib/cjs/rules/a11y/no_unnamed_interactive_element.d.ts +3 -0
- package/lib/cjs/rules/a11y/no_unnamed_interactive_element.d.ts.map +1 -0
- package/lib/cjs/rules/a11y/no_unnamed_interactive_element.js +78 -0
- package/lib/cjs/rules/a11y/no_unnamed_radio_group.d.ts.map +1 -1
- package/lib/cjs/rules/a11y/no_unnamed_radio_group.js +5 -16
- package/lib/cjs/rules/a11y/prefer_eui_icon_tip.d.ts.map +1 -1
- package/lib/cjs/rules/a11y/prefer_eui_icon_tip.js +8 -0
- package/lib/cjs/rules/a11y/require_aria_label_for_modals.d.ts.map +1 -1
- package/lib/cjs/rules/a11y/require_aria_label_for_modals.js +5 -16
- package/lib/cjs/rules/a11y/sr_output_disabled_tooltip.js +2 -2
- package/lib/cjs/rules/a11y/tooltip_focusable_anchor.d.ts +3 -0
- package/lib/cjs/rules/a11y/tooltip_focusable_anchor.d.ts.map +1 -0
- package/lib/cjs/rules/a11y/tooltip_focusable_anchor.js +68 -0
- package/lib/cjs/rules/href_or_on_click.d.ts.map +1 -1
- package/lib/cjs/rules/href_or_on_click.js +5 -16
- package/lib/cjs/rules/no_css_color.d.ts.map +1 -1
- package/lib/cjs/rules/no_css_color.js +14 -7
- package/lib/cjs/rules/no_restricted_eui_imports.d.ts.map +1 -1
- package/lib/cjs/rules/no_restricted_eui_imports.js +5 -16
- package/lib/cjs/utils/are_attrs_equal.d.ts.map +1 -1
- package/lib/cjs/utils/are_attrs_equal.js +5 -16
- package/lib/cjs/utils/constants.d.ts +27 -0
- package/lib/cjs/utils/constants.d.ts.map +1 -0
- package/lib/cjs/utils/constants.js +41 -0
- package/lib/cjs/utils/get_allowed_a11y_prop_names_for_component.d.ts +24 -0
- package/lib/cjs/utils/get_allowed_a11y_prop_names_for_component.d.ts.map +1 -0
- package/lib/cjs/utils/get_allowed_a11y_prop_names_for_component.js +39 -0
- package/lib/cjs/utils/get_attr_value.d.ts +2 -1
- package/lib/cjs/utils/get_attr_value.d.ts.map +1 -1
- package/lib/cjs/utils/get_attr_value.js +11 -18
- package/lib/cjs/utils/has_a11y_prop_for_component.d.ts +20 -0
- package/lib/cjs/utils/has_a11y_prop_for_component.d.ts.map +1 -0
- package/lib/cjs/utils/has_a11y_prop_for_component.js +36 -0
- package/lib/cjs/utils/has_spread.d.ts +12 -0
- package/lib/cjs/utils/has_spread.d.ts.map +1 -0
- package/lib/cjs/utils/has_spread.js +27 -0
- package/lib/cjs/utils/is_in_conditional_rendering.d.ts +3 -0
- package/lib/cjs/utils/is_in_conditional_rendering.d.ts.map +1 -0
- package/lib/cjs/utils/is_in_conditional_rendering.js +24 -0
- package/lib/cjs/utils/resolve_member_expression_root.d.ts.map +1 -1
- package/lib/cjs/utils/resolve_member_expression_root.js +8 -0
- package/lib/esm/index.js +17 -16
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/rules/a11y/accessible_interactive_element.d.ts +2 -0
- package/lib/esm/rules/a11y/accessible_interactive_element.js +50 -0
- package/lib/esm/rules/a11y/accessible_interactive_element.js.map +1 -0
- package/lib/esm/rules/a11y/callout_announce_on_mount.d.ts +2 -0
- package/lib/esm/rules/a11y/callout_announce_on_mount.js +66 -0
- package/lib/esm/rules/a11y/callout_announce_on_mount.js.map +1 -0
- package/lib/esm/rules/a11y/consistent_is_invalid_props.js +7 -18
- package/lib/esm/rules/a11y/consistent_is_invalid_props.js.map +1 -1
- package/lib/esm/rules/a11y/no_unnamed_interactive_element.d.ts +2 -0
- package/lib/esm/rules/a11y/no_unnamed_interactive_element.js +94 -0
- package/lib/esm/rules/a11y/no_unnamed_interactive_element.js.map +1 -0
- package/lib/esm/rules/a11y/no_unnamed_radio_group.js +5 -16
- package/lib/esm/rules/a11y/no_unnamed_radio_group.js.map +1 -1
- package/lib/esm/rules/a11y/prefer_eui_icon_tip.js +7 -0
- package/lib/esm/rules/a11y/prefer_eui_icon_tip.js.map +1 -1
- package/lib/esm/rules/a11y/require_aria_label_for_modals.js +5 -16
- package/lib/esm/rules/a11y/require_aria_label_for_modals.js.map +1 -1
- package/lib/esm/rules/a11y/sr_output_disabled_tooltip.js +2 -2
- package/lib/esm/rules/a11y/sr_output_disabled_tooltip.js.map +1 -1
- package/lib/esm/rules/a11y/tooltip_focusable_anchor.d.ts +2 -0
- package/lib/esm/rules/a11y/tooltip_focusable_anchor.js +84 -0
- package/lib/esm/rules/a11y/tooltip_focusable_anchor.js.map +1 -0
- package/lib/esm/rules/href_or_on_click.js +5 -16
- package/lib/esm/rules/href_or_on_click.js.map +1 -1
- package/lib/esm/rules/no_css_color.js +22 -7
- package/lib/esm/rules/no_css_color.js.map +1 -1
- package/lib/esm/rules/no_restricted_eui_imports.js +5 -16
- package/lib/esm/rules/no_restricted_eui_imports.js.map +1 -1
- package/lib/esm/utils/are_attrs_equal.js +5 -16
- package/lib/esm/utils/are_attrs_equal.js.map +1 -1
- package/lib/esm/utils/constants.d.ts +26 -0
- package/lib/esm/utils/constants.js +119 -0
- package/lib/esm/utils/constants.js.map +1 -0
- package/lib/esm/utils/get_allowed_a11y_prop_names_for_component.d.ts +23 -0
- package/lib/esm/utils/get_allowed_a11y_prop_names_for_component.js +34 -0
- package/lib/esm/utils/get_allowed_a11y_prop_names_for_component.js.map +1 -0
- package/lib/esm/utils/get_attr_value.d.ts +2 -1
- package/lib/esm/utils/get_attr_value.js +11 -18
- package/lib/esm/utils/get_attr_value.js.map +1 -1
- package/lib/esm/utils/has_a11y_prop_for_component.d.ts +19 -0
- package/lib/esm/utils/has_a11y_prop_for_component.js +34 -0
- package/lib/esm/utils/has_a11y_prop_for_component.js.map +1 -0
- package/lib/esm/utils/has_spread.d.ts +11 -0
- package/lib/esm/utils/has_spread.js +23 -0
- package/lib/esm/utils/has_spread.js.map +1 -0
- package/lib/esm/utils/is_in_conditional_rendering.d.ts +2 -0
- package/lib/esm/utils/is_in_conditional_rendering.js +23 -0
- package/lib/esm/utils/is_in_conditional_rendering.js.map +1 -0
- package/lib/esm/utils/resolve_member_expression_root.js +7 -0
- package/lib/esm/utils/resolve_member_expression_root.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,15 +129,15 @@ It's worth pointing out that although the examples provided are specific to EUI
|
|
|
129
129
|
|
|
130
130
|
### `@elastic/eui/require-aria-label-for-modals`
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
Ensure that EUI modal components (`EuiModal`, `EuiFlyout`, `EuiFlyoutResizable` ,`EuiConfirmModal`) have either an `aria-label` or `aria-labelledby` prop for accessibility. This helps screen reader users understand the purpose and content of modal dialogs.
|
|
133
133
|
|
|
134
134
|
### `@elastic/eui/consistent-is-invalid-props`
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
Ensure that form control components within `EuiFormRow` components have matching `isInvalid` prop values. This maintains consistent validation state between parent form rows and their child form controls, leading to a more predictable and accessible user experience.
|
|
137
137
|
|
|
138
138
|
### `@elastic/eui/sr-output-disabled-tooltip`
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
Ensure `disableScreenReaderOutput` is set when `EuiToolTip` content matches `EuiButtonIcon` "aria-label".
|
|
141
141
|
|
|
142
142
|
### `@elastic/eui/prefer-eui-icon-tip`
|
|
143
143
|
|
|
@@ -147,6 +147,21 @@ Ensure `EuiIconTip` is used rather than `<EuiToolTip><EuiIcon/></EuiToolTip>`, a
|
|
|
147
147
|
|
|
148
148
|
Ensure that all radio input components (`EuiRadio`, `EuiRadioGroup`) have a `name` attribute. The `name` attribute is required for radio inputs to be grouped correctly, allowing users to select only one option from a set. Without a `name`, radios may not behave as expected and can cause accessibility issues for assistive technologies.
|
|
149
149
|
|
|
150
|
+
### `@elastic/eui/callout-announce-on-mount`
|
|
151
|
+
|
|
152
|
+
Ensure that `EuiCallOut` components rendered conditionally have the `announceOnMount` prop for better accessibility. When callouts appear dynamically (e.g., after user interactions, form validation errors, or status changes), screen readers may not announce their content to users. The `announceOnMount` prop ensures these messages are properly announced to users with assistive technologies.
|
|
153
|
+
|
|
154
|
+
### `@elastic/eui/no-unnamed-interactive-element`
|
|
155
|
+
|
|
156
|
+
Ensure that appropriate aria-attributes are set for `EuiBetaBadge`, `EuiButtonIcon`, `EuiComboBox`, `EuiSelect`, `EuiSelectWithWidth`,`EuiSuperSelect`,`EuiPagination`, `EuiTreeView`, `EuiBreadcrumbs`. Without this rule, screen reader users lose context, keyboard navigation can be confusing.
|
|
157
|
+
|
|
158
|
+
### `@elastic/eui/tooltip-focusable-anchor`
|
|
159
|
+
|
|
160
|
+
Ensure `EuiTooltip` components are anchored to elements that can receive keyboard focus, making them accessible to all users. When using non-interactive elements (like `span`or `EuiText`) as tooltip anchors, they must include `tabIndex={0}` to be keyboard-focusable. For better accessibility, prefer using semantic interactive components (like `EuiButton` or `EuiLink`) which are focusable by default.
|
|
161
|
+
|
|
162
|
+
### `@elastic/eui/accessible-interactive-element`
|
|
163
|
+
Ensure interactive EUI components (like e.g. `EuiLink`, `EuiButton`, `EuiRadio`) remain accessible by prohibiting `tabIndex={-1}`, which removes them from keyboard navigation.
|
|
164
|
+
|
|
150
165
|
## Testing
|
|
151
166
|
|
|
152
167
|
### Running unit tests
|
package/lib/cjs/index.js
CHANGED
|
@@ -8,23 +8,16 @@ var _consistent_is_invalid_props = require("./rules/a11y/consistent_is_invalid_p
|
|
|
8
8
|
var _sr_output_disabled_tooltip = require("./rules/a11y/sr_output_disabled_tooltip");
|
|
9
9
|
var _prefer_eui_icon_tip = require("./rules/a11y/prefer_eui_icon_tip");
|
|
10
10
|
var _no_unnamed_radio_group = require("./rules/a11y/no_unnamed_radio_group");
|
|
11
|
+
var _no_unnamed_interactive_element = require("./rules/a11y/no_unnamed_interactive_element");
|
|
12
|
+
var _tooltip_focusable_anchor = require("./rules/a11y/tooltip_focusable_anchor");
|
|
13
|
+
var _callout_announce_on_mount = require("./rules/a11y/callout_announce_on_mount");
|
|
14
|
+
var _accessible_interactive_element = require("./rules/a11y/accessible_interactive_element");
|
|
11
15
|
/*
|
|
12
|
-
*
|
|
13
|
-
* license agreements.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* not use this file except in compliance with the License.
|
|
18
|
-
* You may obtain a copy of the License at
|
|
19
|
-
*
|
|
20
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
21
|
-
*
|
|
22
|
-
* Unless required by applicable law or agreed to in writing,
|
|
23
|
-
* software distributed under the License is distributed on an
|
|
24
|
-
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
25
|
-
* KIND, either express or implied. See the License for the
|
|
26
|
-
* specific language governing permissions and limitations
|
|
27
|
-
* under the License.
|
|
16
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
17
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
18
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
19
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
20
|
+
* Side Public License, v 1.
|
|
28
21
|
*/
|
|
29
22
|
|
|
30
23
|
const config = {
|
|
@@ -36,7 +29,11 @@ const config = {
|
|
|
36
29
|
'consistent-is-invalid-props': _consistent_is_invalid_props.ConsistentIsInvalidProps,
|
|
37
30
|
'sr-output-disabled-tooltip': _sr_output_disabled_tooltip.ScreenReaderOutputDisabledTooltip,
|
|
38
31
|
'prefer-eui-icon-tip': _prefer_eui_icon_tip.PreferEuiIconTip,
|
|
39
|
-
'no-unnamed-radio-group': _no_unnamed_radio_group.NoUnnamedRadioGroup
|
|
32
|
+
'no-unnamed-radio-group': _no_unnamed_radio_group.NoUnnamedRadioGroup,
|
|
33
|
+
'callout-announce-on-mount': _callout_announce_on_mount.CallOutAnnounceOnMount,
|
|
34
|
+
'no-unnamed-interactive-element': _no_unnamed_interactive_element.NoUnnamedInteractiveElement,
|
|
35
|
+
'tooltip-focusable-anchor': _tooltip_focusable_anchor.TooltipFocusableAnchor,
|
|
36
|
+
'accessible-interactive-element': _accessible_interactive_element.AccessibleInteractiveElements
|
|
40
37
|
},
|
|
41
38
|
configs: {
|
|
42
39
|
recommended: {
|
|
@@ -49,7 +46,11 @@ const config = {
|
|
|
49
46
|
'@elastic/eui/consistent-is-invalid-props': 'warn',
|
|
50
47
|
'@elastic/eui/sr-output-disabled-tooltip': 'warn',
|
|
51
48
|
'@elastic/eui/prefer-eui-icon-tip': 'warn',
|
|
52
|
-
'@elastic/eui/no-unnamed-radio-group': 'warn'
|
|
49
|
+
'@elastic/eui/no-unnamed-radio-group': 'warn',
|
|
50
|
+
'@elastic/eui/callout-announce-on-mount': 'warn',
|
|
51
|
+
'@elastic/eui/no-unnamed-interactive-element': 'warn',
|
|
52
|
+
'@elastic/eui/tooltip-focusable-anchor': 'warn',
|
|
53
|
+
'@elastic/eui/accessible-interactive-element': 'warn'
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessible_interactive_element.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/accessible_interactive_element.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAiB,MAAM,0BAA0B,CAAC;AAItE,eAAO,MAAM,6BAA6B,mFAuCxC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.AccessibleInteractiveElements = void 0;
|
|
7
|
+
var _utils = require("@typescript-eslint/utils");
|
|
8
|
+
var _constants = require("../../utils/constants");
|
|
9
|
+
var _get_attr_value = require("../../utils/get_attr_value");
|
|
10
|
+
/*
|
|
11
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
12
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
13
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
14
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
15
|
+
* Side Public License, v 1.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const AccessibleInteractiveElements = exports.AccessibleInteractiveElements = _utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
19
|
+
create(context) {
|
|
20
|
+
return {
|
|
21
|
+
JSXOpeningElement(node) {
|
|
22
|
+
if (node.name.type !== 'JSXIdentifier') return;
|
|
23
|
+
const componentName = node.name.name;
|
|
24
|
+
if (!_constants.INTERACTIVE_EUI_COMPONENTS.includes(componentName)) return;
|
|
25
|
+
const tabIndexAttribute = node.attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier' && attr.name.name === 'tabIndex');
|
|
26
|
+
if (tabIndexAttribute && (Number((0, _get_attr_value.extractAttrValue)(context, tabIndexAttribute)) || 0) === -1) {
|
|
27
|
+
context.report({
|
|
28
|
+
node: node,
|
|
29
|
+
messageId: 'disallowTabIndex',
|
|
30
|
+
data: {
|
|
31
|
+
component: componentName
|
|
32
|
+
},
|
|
33
|
+
fix: fixer => fixer.remove(tabIndexAttribute)
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
meta: {
|
|
40
|
+
type: 'problem',
|
|
41
|
+
docs: {
|
|
42
|
+
description: 'Ensure interactive EUI components remain accessible by prohibiting tabIndex={-1}, which removes them from keyboard navigation.'
|
|
43
|
+
},
|
|
44
|
+
fixable: 'code',
|
|
45
|
+
schema: [],
|
|
46
|
+
messages: {
|
|
47
|
+
disallowTabIndex: '{{component}} is an interactive EUI component and must not use tabIndex={-1}, as this removes it from keyboard navigation and impairs accessibility.'
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
defaultOptions: []
|
|
51
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callout_announce_on_mount.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/callout_announce_on_mount.ts"],"names":[],"mappings":"AAQA,OAAO,EAAG,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMxD,eAAO,MAAM,sBAAsB,yFAuDjC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.CallOutAnnounceOnMount = void 0;
|
|
7
|
+
var _utils = require("@typescript-eslint/utils");
|
|
8
|
+
var _is_in_conditional_rendering = require("../../utils/is_in_conditional_rendering");
|
|
9
|
+
var _has_spread = require("../../utils/has_spread");
|
|
10
|
+
/*
|
|
11
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
12
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
13
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
14
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
15
|
+
* Side Public License, v 1.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const CALLOUT_COMPONENT = 'EuiCallOut';
|
|
19
|
+
const CallOutAnnounceOnMount = exports.CallOutAnnounceOnMount = _utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
JSXElement(node) {
|
|
23
|
+
const {
|
|
24
|
+
openingElement
|
|
25
|
+
} = node;
|
|
26
|
+
if (openingElement.name.type !== 'JSXIdentifier' || openingElement.name.name !== CALLOUT_COMPONENT) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (openingElement.attributes.some(attr => attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier' && attr.name.name === 'announceOnMount')) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if ((0, _is_in_conditional_rendering.isInConditionalRendering)(node)) {
|
|
33
|
+
context.report({
|
|
34
|
+
node: openingElement,
|
|
35
|
+
messageId: 'missingAnnounceOnMount',
|
|
36
|
+
fix: (0, _has_spread.hasSpread)(openingElement.attributes) ? undefined : fixer => {
|
|
37
|
+
return fixer.insertTextAfterRange([openingElement.name.range[1], openingElement.name.range[1]], ' announceOnMount');
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
meta: {
|
|
45
|
+
type: 'problem',
|
|
46
|
+
docs: {
|
|
47
|
+
description: `Ensure ${CALLOUT_COMPONENT} components that are conditionally rendered have announceOnMount prop for better accessibility`
|
|
48
|
+
},
|
|
49
|
+
fixable: 'code',
|
|
50
|
+
schema: [],
|
|
51
|
+
messages: {
|
|
52
|
+
missingAnnounceOnMount: [`${CALLOUT_COMPONENT} should have \`announceOnMount\` prop when conditionally rendered for better accessibility.`, '\n', `When ${CALLOUT_COMPONENT} appears dynamically (e.g., after user interaction, form validation, etc.),`, 'screen readers may not announce its content. Adding `announceOnMount` ensures the callout', 'is properly announced to users with assistive technologies.', '\n', `Note: If ${CALLOUT_COMPONENT} is inside a condition and not an action, explicitly set \`announceOnMount={false}\``, 'Example:', ` <${CALLOUT_COMPONENT} announceOnMount title="Error" color="danger">`, ' This message will be announced when it appears', ` </${CALLOUT_COMPONENT}>`].join('\n')
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
defaultOptions: []
|
|
56
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consistent_is_invalid_props.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/consistent_is_invalid_props.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"consistent_is_invalid_props.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/consistent_is_invalid_props.ts"],"names":[],"mappings":"AAQA,OAAO,EAAiB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAiBtE,eAAO,MAAM,wBAAwB,wFA6FnC,CAAC"}
|
|
@@ -8,22 +8,11 @@ var _utils = require("@typescript-eslint/utils");
|
|
|
8
8
|
var _get_attr_value = require("../../utils/get_attr_value");
|
|
9
9
|
var _are_attrs_equal = require("../../utils/are_attrs_equal");
|
|
10
10
|
/*
|
|
11
|
-
*
|
|
12
|
-
* license agreements.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* not use this file except in compliance with the License.
|
|
17
|
-
* You may obtain a copy of the License at
|
|
18
|
-
*
|
|
19
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
20
|
-
*
|
|
21
|
-
* Unless required by applicable law or agreed to in writing,
|
|
22
|
-
* software distributed under the License is distributed on an
|
|
23
|
-
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
24
|
-
* KIND, either express or implied. See the License for the
|
|
25
|
-
* specific language governing permissions and limitations
|
|
26
|
-
* under the License.
|
|
11
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
12
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
13
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
14
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
15
|
+
* Side Public License, v 1.
|
|
27
16
|
*/
|
|
28
17
|
|
|
29
18
|
const formControlComponent = 'EuiFormRow';
|
|
@@ -36,7 +25,7 @@ const ConsistentIsInvalidProps = exports.ConsistentIsInvalidProps = _utils.ESLin
|
|
|
36
25
|
if (openingElement?.name.type !== 'JSXIdentifier' || openingElement.name.name !== formControlComponent || openingElement.attributes.length === 0) {
|
|
37
26
|
return;
|
|
38
27
|
}
|
|
39
|
-
const formRowIsInvalid = (0, _get_attr_value.
|
|
28
|
+
const formRowIsInvalid = (0, _get_attr_value.findAttrValue)(context, openingElement.attributes, 'isInvalid');
|
|
40
29
|
if (formRowIsInvalid === undefined) {
|
|
41
30
|
return;
|
|
42
31
|
}
|
|
@@ -44,7 +33,7 @@ const ConsistentIsInvalidProps = exports.ConsistentIsInvalidProps = _utils.ESLin
|
|
|
44
33
|
if (!childElement) {
|
|
45
34
|
return;
|
|
46
35
|
}
|
|
47
|
-
const childIsInvalid = (0, _get_attr_value.
|
|
36
|
+
const childIsInvalid = (0, _get_attr_value.findAttrValue)(context, childElement.openingElement.attributes, 'isInvalid');
|
|
48
37
|
if (!(0, _are_attrs_equal.areAttrsEqual)(childIsInvalid, formRowIsInvalid)) {
|
|
49
38
|
const componentName = childElement.openingElement.name.name;
|
|
50
39
|
context.report({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no_unnamed_interactive_element.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/no_unnamed_interactive_element.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAiB,MAAM,0BAA0B,CAAC;AA+BtE,eAAO,MAAM,2BAA2B,8EAyEtC,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.NoUnnamedInteractiveElement = void 0;
|
|
7
|
+
var _utils = require("@typescript-eslint/utils");
|
|
8
|
+
var _has_spread = require("../../utils/has_spread");
|
|
9
|
+
var _get_allowed_a11y_prop_names_for_component = require("../../utils/get_allowed_a11y_prop_names_for_component");
|
|
10
|
+
var _has_a11y_prop_for_component = require("../../utils/has_a11y_prop_for_component");
|
|
11
|
+
/*
|
|
12
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
13
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
14
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
15
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
16
|
+
* Side Public License, v 1.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const interactiveComponents = ['EuiBetaBadge', 'EuiButtonIcon', 'EuiComboBox', 'EuiSelect', 'EuiSelectWithWidth', 'EuiSuperSelect', 'EuiPagination', 'EuiTreeView', 'EuiBreadcrumbs'];
|
|
20
|
+
const wrappingComponents = ['EuiFormRow'];
|
|
21
|
+
const interactiveComponentsWithLabel = ['EuiBetaBadge'];
|
|
22
|
+
const baseA11yProps = ['aria-label', 'aria-labelledby'];
|
|
23
|
+
|
|
24
|
+
// Single source of truth for the utils (keeps them reusable)
|
|
25
|
+
const a11yConfig = {
|
|
26
|
+
interactiveComponentsWithLabel: [...interactiveComponentsWithLabel],
|
|
27
|
+
wrappingComponents: [...wrappingComponents],
|
|
28
|
+
baseA11yProps: [...baseA11yProps]
|
|
29
|
+
};
|
|
30
|
+
const NoUnnamedInteractiveElement = exports.NoUnnamedInteractiveElement = _utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
31
|
+
meta: {
|
|
32
|
+
type: 'problem',
|
|
33
|
+
hasSuggestions: false,
|
|
34
|
+
schema: [],
|
|
35
|
+
messages: {
|
|
36
|
+
missingA11y: '{{component}} must include an accessible label. Use one of: {{a11yProps}}'
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
defaultOptions: [],
|
|
40
|
+
create(context) {
|
|
41
|
+
const sourceCode = context.sourceCode;
|
|
42
|
+
function report(opening) {
|
|
43
|
+
if (opening.name.type !== 'JSXIdentifier') return;
|
|
44
|
+
const component = opening.name.name;
|
|
45
|
+
const allowed = (0, _get_allowed_a11y_prop_names_for_component.getAllowedA11yPropNamesForComponent)(component, a11yConfig).join(', ');
|
|
46
|
+
context.report({
|
|
47
|
+
node: opening,
|
|
48
|
+
messageId: 'missingA11y',
|
|
49
|
+
data: {
|
|
50
|
+
component,
|
|
51
|
+
a11yProps: allowed
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
JSXOpeningElement(node) {
|
|
57
|
+
if (node.name.type !== 'JSXIdentifier') return;
|
|
58
|
+
const componentName = node.name.name;
|
|
59
|
+
const isInteractive = interactiveComponents.includes(componentName);
|
|
60
|
+
if (!isInteractive) return;
|
|
61
|
+
if ((0, _has_spread.hasSpread)(node.attributes) || (0, _has_a11y_prop_for_component.hasA11yPropForComponent)(componentName, node.attributes, a11yConfig)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const ancestors = sourceCode.getAncestors(node);
|
|
65
|
+
const wrapper = [...ancestors].reverse().find(a => a.type === 'JSXElement' && a.openingElement.name.type === 'JSXIdentifier' && wrappingComponents.includes(a.openingElement.name.name));
|
|
66
|
+
if (wrapper) {
|
|
67
|
+
const open = wrapper.openingElement;
|
|
68
|
+
const wrapperName = open.name.type === 'JSXIdentifier' ? open.name.name : '';
|
|
69
|
+
if (!(0, _has_spread.hasSpread)(open.attributes) && !(0, _has_a11y_prop_for_component.hasA11yPropForComponent)(wrapperName, open.attributes, a11yConfig)) {
|
|
70
|
+
report(open);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
report(node);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no_unnamed_radio_group.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/no_unnamed_radio_group.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"no_unnamed_radio_group.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/no_unnamed_radio_group.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAIvD,eAAO,MAAM,mBAAmB,mFAuC9B,CAAC"}
|
|
@@ -6,22 +6,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.NoUnnamedRadioGroup = void 0;
|
|
7
7
|
var _utils = require("@typescript-eslint/utils");
|
|
8
8
|
/*
|
|
9
|
-
*
|
|
10
|
-
* license agreements.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* not use this file except in compliance with the License.
|
|
15
|
-
* You may obtain a copy of the License at
|
|
16
|
-
*
|
|
17
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
-
*
|
|
19
|
-
* Unless required by applicable law or agreed to in writing,
|
|
20
|
-
* software distributed under the License is distributed on an
|
|
21
|
-
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
22
|
-
* KIND, either express or implied. See the License for the
|
|
23
|
-
* specific language governing permissions and limitations
|
|
24
|
-
* under the License.
|
|
9
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
10
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
11
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
12
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
13
|
+
* Side Public License, v 1.
|
|
25
14
|
*/
|
|
26
15
|
|
|
27
16
|
const radioComponents = ['EuiRadio', 'EuiRadioGroup'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer_eui_icon_tip.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/prefer_eui_icon_tip.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prefer_eui_icon_tip.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/prefer_eui_icon_tip.ts"],"names":[],"mappings":"AAQA,OAAO,EAAiB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMtE,eAAO,MAAM,gBAAgB,mFA0C3B,CAAC"}
|
|
@@ -5,6 +5,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.PreferEuiIconTip = void 0;
|
|
7
7
|
var _utils = require("@typescript-eslint/utils");
|
|
8
|
+
/*
|
|
9
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
10
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
11
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
12
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
13
|
+
* Side Public License, v 1.
|
|
14
|
+
*/
|
|
15
|
+
|
|
8
16
|
const TOOLTIP_COMPONENT = 'EuiToolTip';
|
|
9
17
|
const ICON_COMPONENT = 'EuiIcon';
|
|
10
18
|
const ICON_TIP_COMPONENT = 'EuiIconTip';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require_aria_label_for_modals.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/require_aria_label_for_modals.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"require_aria_label_for_modals.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/require_aria_label_for_modals.ts"],"names":[],"mappings":"AAQA,OAAO,EAAY,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAKjE,eAAO,MAAM,yBAAyB,+GA0FpC,CAAC"}
|
|
@@ -6,22 +6,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.RequireAriaLabelForModals = void 0;
|
|
7
7
|
var _utils = require("@typescript-eslint/utils");
|
|
8
8
|
/*
|
|
9
|
-
*
|
|
10
|
-
* license agreements.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* not use this file except in compliance with the License.
|
|
15
|
-
* You may obtain a copy of the License at
|
|
16
|
-
*
|
|
17
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
-
*
|
|
19
|
-
* Unless required by applicable law or agreed to in writing,
|
|
20
|
-
* software distributed under the License is distributed on an
|
|
21
|
-
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
22
|
-
* KIND, either express or implied. See the License for the
|
|
23
|
-
* specific language governing permissions and limitations
|
|
24
|
-
* under the License.
|
|
9
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
10
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
11
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
12
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
13
|
+
* Side Public License, v 1.
|
|
25
14
|
*/
|
|
26
15
|
|
|
27
16
|
const modalComponents = ['EuiModal', 'EuiFlyout', 'EuiFlyoutResizable'];
|
|
@@ -26,7 +26,7 @@ const ScreenReaderOutputDisabledTooltip = exports.ScreenReaderOutputDisabledTool
|
|
|
26
26
|
if (openingElement?.name.type !== 'JSXIdentifier' || openingElement.name.name !== tooltipComponent) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
-
const tooltipContent = (0, _get_attr_value.
|
|
29
|
+
const tooltipContent = (0, _get_attr_value.findAttrValue)(context, openingElement.attributes, 'content');
|
|
30
30
|
const hasDisableScreenReader = openingElement.attributes.some(attr => attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier' && attr.name.name === disabledTooltipComponentProp);
|
|
31
31
|
if (hasDisableScreenReader) {
|
|
32
32
|
return;
|
|
@@ -35,7 +35,7 @@ const ScreenReaderOutputDisabledTooltip = exports.ScreenReaderOutputDisabledTool
|
|
|
35
35
|
if (!buttonElement) {
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
|
-
const ariaLabel = (0, _get_attr_value.
|
|
38
|
+
const ariaLabel = (0, _get_attr_value.findAttrValue)(context, buttonElement.openingElement.attributes, 'aria-label');
|
|
39
39
|
if (tooltipContent && ariaLabel && (0, _are_attrs_equal.areAttrsEqual)(tooltipContent, ariaLabel)) {
|
|
40
40
|
const buttonElementName = buttonElement.openingElement.name.name;
|
|
41
41
|
context.report({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip_focusable_anchor.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/tooltip_focusable_anchor.ts"],"names":[],"mappings":"AAQA,OAAO,EAAY,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAoBjE,eAAO,MAAM,sBAAsB,0FAyEjC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TooltipFocusableAnchor = void 0;
|
|
7
|
+
var _utils = require("@typescript-eslint/utils");
|
|
8
|
+
var _constants = require("../../utils/constants");
|
|
9
|
+
/*
|
|
10
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
11
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
12
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
13
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
14
|
+
* Side Public License, v 1.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const TOOL_TIP_COMPONENT = 'EuiToolTip';
|
|
18
|
+
const NON_INTERACTIVE_ELEMENTS = [..._constants.NON_INTERACTIVE_HTML_TAGS,
|
|
19
|
+
// note: not a complete list, based on the most common violations
|
|
20
|
+
'EuiText', 'EuiImage', 'EuiBadge', 'EuiBetaBadge'];
|
|
21
|
+
const INTERACTIVE_ATTRS = ['tabIndex', 'href', 'onClick'];
|
|
22
|
+
const TooltipFocusableAnchor = exports.TooltipFocusableAnchor = _utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
23
|
+
create(context) {
|
|
24
|
+
const isTooltipComponent = node => node.name.type === 'JSXIdentifier' && node.name.name === TOOL_TIP_COMPONENT;
|
|
25
|
+
const hasInteractiveAttribute = node => node.attributes.some(attr => attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier' && INTERACTIVE_ATTRS.includes(attr.name.name));
|
|
26
|
+
const isNonInteractiveElement = elementName => NON_INTERACTIVE_ELEMENTS.includes(elementName);
|
|
27
|
+
return {
|
|
28
|
+
JSXElement(node) {
|
|
29
|
+
const {
|
|
30
|
+
openingElement
|
|
31
|
+
} = node;
|
|
32
|
+
if (!isTooltipComponent(openingElement)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const children = node.children.filter(child => child.type === 'JSXElement');
|
|
36
|
+
if (children.length === 0) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const firstChild = children[0].openingElement;
|
|
40
|
+
if (firstChild.name.type !== 'JSXIdentifier') {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const childName = firstChild.name.name;
|
|
44
|
+
if (isNonInteractiveElement(childName) && !hasInteractiveAttribute(firstChild)) {
|
|
45
|
+
context.report({
|
|
46
|
+
node: firstChild,
|
|
47
|
+
messageId: 'requiresFocusableAnchor',
|
|
48
|
+
data: {
|
|
49
|
+
element: childName,
|
|
50
|
+
toolTipComponent: TOOL_TIP_COMPONENT
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
meta: {
|
|
58
|
+
type: 'problem',
|
|
59
|
+
docs: {
|
|
60
|
+
description: 'Ensure {{ toolTipComponent }} components are anchored to focusable elements'
|
|
61
|
+
},
|
|
62
|
+
schema: [],
|
|
63
|
+
messages: {
|
|
64
|
+
requiresFocusableAnchor: ['{{ element }} inside {{ toolTipComponent }} must be focusable for accessibility.', 'Option 1: Add tabIndex attribute to make the element keyboard focusable:', ' <{{ toolTipComponent }} content=\'...\'>', ' <{{ element }} tabIndex={0}>...</{{ element }}>', ' </{{ toolTipComponent }}>', 'Option 2 (Preferred): Use an interactive component instead:', ' <{{ toolTipComponent }} content=\'...\'>', ' <EuiButton>...</EuiButton>', ' </{{ toolTipComponent }}>'].join('\n')
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
defaultOptions: []
|
|
68
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"href_or_on_click.d.ts","sourceRoot":"","sources":["../../../src/rules/href_or_on_click.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"href_or_on_click.d.ts","sourceRoot":"","sources":["../../../src/rules/href_or_on_click.ts"],"names":[],"mappings":"AAQA,OAAO,EAAY,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAIjE,eAAO,MAAM,WAAW,gFA8CtB,CAAC"}
|
|
@@ -6,22 +6,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.HrefOnClick = void 0;
|
|
7
7
|
var _utils = require("@typescript-eslint/utils");
|
|
8
8
|
/*
|
|
9
|
-
*
|
|
10
|
-
* license agreements.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* not use this file except in compliance with the License.
|
|
15
|
-
* You may obtain a copy of the License at
|
|
16
|
-
*
|
|
17
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
-
*
|
|
19
|
-
* Unless required by applicable law or agreed to in writing,
|
|
20
|
-
* software distributed under the License is distributed on an
|
|
21
|
-
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
22
|
-
* KIND, either express or implied. See the License for the
|
|
23
|
-
* specific language governing permissions and limitations
|
|
24
|
-
* under the License.
|
|
9
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
10
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
11
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
12
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
13
|
+
* Side Public License, v 1.
|
|
25
14
|
*/
|
|
26
15
|
|
|
27
16
|
const componentNames = ['EuiButton', 'EuiButtonEmpty', 'EuiLink', 'EuiBadge'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no_css_color.d.ts","sourceRoot":"","sources":["../../../src/rules/no_css_color.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"no_css_color.d.ts","sourceRoot":"","sources":["../../../src/rules/no_css_color.ts"],"names":[],"mappings":"AASA,OAAO,EAAY,WAAW,EAAE,MAAM,0BAA0B,CAAC;AA4OjE,eAAO,MAAM,UAAU,2IAsRrB,CAAC"}
|
|
@@ -9,11 +9,10 @@ var _utils = require("@typescript-eslint/utils");
|
|
|
9
9
|
var _resolve_member_expression_root = require("../utils/resolve_member_expression_root");
|
|
10
10
|
/*
|
|
11
11
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
12
|
-
* or more contributor license agreements. Licensed under the
|
|
13
|
-
* 2.0
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* License v3.0 only", or the "Server Side Public License, v 1".
|
|
12
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
13
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
14
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
15
|
+
* Side Public License, v 1.
|
|
17
16
|
*/
|
|
18
17
|
|
|
19
18
|
/**
|
|
@@ -39,9 +38,17 @@ const checkPropertySpecifiesInvalidCSSColor = ([property, value]) => {
|
|
|
39
38
|
// build the resolved color property to check if the value is a string after parsing the style declaration
|
|
40
39
|
const resolvedColorProperty = anchor === 'color' ? 'color' : anchor + 'Color';
|
|
41
40
|
|
|
42
|
-
// in trying to keep this rule simple, it's enough if we get a value back, because if it was an identifier we would have been able to set a value within this invocation
|
|
43
41
|
// @ts-expect-error the types for this packages specifics an index signature of number, alongside other valid CSS properties
|
|
44
|
-
|
|
42
|
+
const colorValue = style[resolvedColorProperty];
|
|
43
|
+
if (!colorValue) return false;
|
|
44
|
+
|
|
45
|
+
// Allow CSS keywords that are valid and should not trigger warnings
|
|
46
|
+
const allowedCssKeywords = ['currentcolor', 'transparent', 'inherit', 'initial', 'unset', 'revert', 'revert-layer'];
|
|
47
|
+
const normalizedColorValue = colorValue.toLowerCase().trim();
|
|
48
|
+
if (allowedCssKeywords.includes(normalizedColorValue)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
45
52
|
};
|
|
46
53
|
|
|
47
54
|
/**
|