@elastic/eslint-plugin-eui 2.5.0 → 2.6.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 +5 -0
- package/lib/cjs/index.js +5 -2
- package/lib/cjs/rules/a11y/require_table_caption.d.ts +3 -0
- package/lib/cjs/rules/a11y/require_table_caption.d.ts.map +1 -0
- package/lib/cjs/rules/a11y/require_table_caption.js +53 -0
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/rules/a11y/require_table_caption.d.ts +2 -0
- package/lib/esm/rules/a11y/require_table_caption.js +55 -0
- package/lib/esm/rules/a11y/require_table_caption.js.map +1 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -160,8 +160,13 @@ Ensure that appropriate aria-attributes are set for `EuiBetaBadge`, `EuiButtonIc
|
|
|
160
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
161
|
|
|
162
162
|
### `@elastic/eui/accessible-interactive-element`
|
|
163
|
+
|
|
163
164
|
Ensure interactive EUI components (like e.g. `EuiLink`, `EuiButton`, `EuiRadio`) remain accessible by prohibiting `tabIndex={-1}`, which removes them from keyboard navigation.
|
|
164
165
|
|
|
166
|
+
### `@elastic/eui/require-table-caption`
|
|
167
|
+
|
|
168
|
+
Ensure `EuiInMemoryTable`, `EuiBasicTable` have a `tableCaption` property for accessibility.
|
|
169
|
+
|
|
165
170
|
## Testing
|
|
166
171
|
|
|
167
172
|
### Running unit tests
|
package/lib/cjs/index.js
CHANGED
|
@@ -12,6 +12,7 @@ var _no_unnamed_interactive_element = require("./rules/a11y/no_unnamed_interacti
|
|
|
12
12
|
var _tooltip_focusable_anchor = require("./rules/a11y/tooltip_focusable_anchor");
|
|
13
13
|
var _callout_announce_on_mount = require("./rules/a11y/callout_announce_on_mount");
|
|
14
14
|
var _accessible_interactive_element = require("./rules/a11y/accessible_interactive_element");
|
|
15
|
+
var _require_table_caption = require("./rules/a11y/require_table_caption");
|
|
15
16
|
/*
|
|
16
17
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
17
18
|
* or more contributor license agreements. Licensed under the Elastic License
|
|
@@ -33,7 +34,8 @@ const config = {
|
|
|
33
34
|
'callout-announce-on-mount': _callout_announce_on_mount.CallOutAnnounceOnMount,
|
|
34
35
|
'no-unnamed-interactive-element': _no_unnamed_interactive_element.NoUnnamedInteractiveElement,
|
|
35
36
|
'tooltip-focusable-anchor': _tooltip_focusable_anchor.TooltipFocusableAnchor,
|
|
36
|
-
'accessible-interactive-element': _accessible_interactive_element.AccessibleInteractiveElements
|
|
37
|
+
'accessible-interactive-element': _accessible_interactive_element.AccessibleInteractiveElements,
|
|
38
|
+
'require-table-caption': _require_table_caption.RequireTableCaption
|
|
37
39
|
},
|
|
38
40
|
configs: {
|
|
39
41
|
recommended: {
|
|
@@ -50,7 +52,8 @@ const config = {
|
|
|
50
52
|
'@elastic/eui/callout-announce-on-mount': 'warn',
|
|
51
53
|
'@elastic/eui/no-unnamed-interactive-element': 'warn',
|
|
52
54
|
'@elastic/eui/tooltip-focusable-anchor': 'warn',
|
|
53
|
-
'@elastic/eui/accessible-interactive-element': 'warn'
|
|
55
|
+
'@elastic/eui/accessible-interactive-element': 'warn',
|
|
56
|
+
'@elastic/eui/require-table-caption': 'warn'
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
59
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require_table_caption.d.ts","sourceRoot":"","sources":["../../../../src/rules/a11y/require_table_caption.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAiB,MAAM,0BAA0B,CAAC;AAKtE,eAAO,MAAM,mBAAmB,sFA+C9B,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.RequireTableCaption = void 0;
|
|
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
|
+
|
|
16
|
+
const TABLE_COMPONENTS = ['EuiInMemoryTable', 'EuiBasicTable'];
|
|
17
|
+
const TABLE_CAPTION_PROP = 'tableCaption';
|
|
18
|
+
const RequireTableCaption = exports.RequireTableCaption = _utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
19
|
+
create(context) {
|
|
20
|
+
return {
|
|
21
|
+
JSXOpeningElement(node) {
|
|
22
|
+
if (node.name.type !== 'JSXIdentifier') {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const component = node.name.name;
|
|
26
|
+
if (!TABLE_COMPONENTS.includes(component)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const hasTableCaption = node.attributes.some(attr => attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier' && attr.name.name === TABLE_CAPTION_PROP);
|
|
30
|
+
if (!hasTableCaption) {
|
|
31
|
+
context.report({
|
|
32
|
+
node,
|
|
33
|
+
messageId: 'missingTableCaption',
|
|
34
|
+
data: {
|
|
35
|
+
component
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
defaultOptions: [],
|
|
43
|
+
meta: {
|
|
44
|
+
type: 'problem',
|
|
45
|
+
docs: {
|
|
46
|
+
description: `Ensure ${TABLE_COMPONENTS.join(', ')} have a \`${TABLE_CAPTION_PROP}\` prop for accessibility.`
|
|
47
|
+
},
|
|
48
|
+
schema: [],
|
|
49
|
+
messages: {
|
|
50
|
+
missingTableCaption: ['{{component}} must include a `tableCaption` prop for accessibility.', '', 'Example:', ' <{{component}} tableCaption="Descriptive caption for the table" ... />'].join('\n')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
package/lib/esm/index.js
CHANGED
|
@@ -19,6 +19,7 @@ const no_unnamed_interactive_element_1 = require("./rules/a11y/no_unnamed_intera
|
|
|
19
19
|
const tooltip_focusable_anchor_1 = require("./rules/a11y/tooltip_focusable_anchor");
|
|
20
20
|
const callout_announce_on_mount_1 = require("./rules/a11y/callout_announce_on_mount");
|
|
21
21
|
const accessible_interactive_element_1 = require("./rules/a11y/accessible_interactive_element");
|
|
22
|
+
const require_table_caption_1 = require("./rules/a11y/require_table_caption");
|
|
22
23
|
const config = {
|
|
23
24
|
rules: {
|
|
24
25
|
'href-or-on-click': href_or_on_click_1.HrefOnClick,
|
|
@@ -33,6 +34,7 @@ const config = {
|
|
|
33
34
|
'no-unnamed-interactive-element': no_unnamed_interactive_element_1.NoUnnamedInteractiveElement,
|
|
34
35
|
'tooltip-focusable-anchor': tooltip_focusable_anchor_1.TooltipFocusableAnchor,
|
|
35
36
|
'accessible-interactive-element': accessible_interactive_element_1.AccessibleInteractiveElements,
|
|
37
|
+
'require-table-caption': require_table_caption_1.RequireTableCaption,
|
|
36
38
|
},
|
|
37
39
|
configs: {
|
|
38
40
|
recommended: {
|
|
@@ -50,6 +52,7 @@ const config = {
|
|
|
50
52
|
'@elastic/eui/no-unnamed-interactive-element': 'warn',
|
|
51
53
|
'@elastic/eui/tooltip-focusable-anchor': 'warn',
|
|
52
54
|
'@elastic/eui/accessible-interactive-element': 'warn',
|
|
55
|
+
'@elastic/eui/require-table-caption': 'warn',
|
|
53
56
|
},
|
|
54
57
|
},
|
|
55
58
|
},
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAGH,+DAAuD;AACvD,iFAA2E;AAC3E,uDAAkD;AAElD,8FAAuF;AACvF,0FAAoF;AACpF,wFAA4F;AAC5F,0EAAoE;AACpE,gFAA0E;AAC1E,gGAA0F;AAC1F,oFAA+E;AAC/E,sFAAgF;AAChF,gGAA4F;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAGH,+DAAuD;AACvD,iFAA2E;AAC3E,uDAAkD;AAElD,8FAAuF;AACvF,0FAAoF;AACpF,wFAA4F;AAC5F,0EAAoE;AACpE,gFAA0E;AAC1E,gGAA0F;AAC1F,oFAA+E;AAC/E,sFAAgF;AAChF,gGAA4F;AAC5F,8EAAyE;AAEzE,MAAM,MAAM,GAAG;IACb,KAAK,EAAE;QACL,kBAAkB,EAAE,8BAAW;QAC/B,2BAA2B,EAAE,kDAAsB;QACnD,cAAc,EAAE,yBAAU;QAC1B,+BAA+B,EAAE,yDAAyB;QAC1D,6BAA6B,EAAE,sDAAwB;QACvD,4BAA4B,EAAE,8DAAiC;QAC/D,qBAAqB,EAAE,sCAAgB;QACvC,wBAAwB,EAAG,4CAAmB;QAC9C,2BAA2B,EAAE,kDAAsB;QACnD,gCAAgC,EAAE,4DAA2B;QAC7D,0BAA0B,EAAE,iDAAsB;QAClD,gCAAgC,EAAE,8DAA6B;QAC/D,uBAAuB,EAAE,2CAAmB;KAC7C;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,4BAA4B,CAAC;YACvC,KAAK,EAAE;gBACL,+BAA+B,EAAE,MAAM;gBACvC,wCAAwC,EAAE,MAAM;gBAChD,2BAA2B,EAAE,MAAM;gBACnC,4CAA4C,EAAE,MAAM;gBACpD,0CAA0C,EAAE,MAAM;gBAClD,yCAAyC,EAAE,MAAM;gBACjD,kCAAkC,EAAE,MAAM;gBAC1C,qCAAqC,EAAE,MAAM;gBAC7C,wCAAwC,EAAE,MAAM;gBAChD,6CAA6C,EAAE,MAAM;gBACrD,uCAAuC,EAAE,MAAM;gBAC/C,6CAA6C,EAAE,MAAM;gBACrD,oCAAoC,EAAE,MAAM;aAC7C;SACF;KACF;CACF,CAAC;AAEF,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
4
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
5
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
6
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
7
|
+
* Side Public License, v 1.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.RequireTableCaption = void 0;
|
|
11
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
12
|
+
const TABLE_COMPONENTS = ['EuiInMemoryTable', 'EuiBasicTable'];
|
|
13
|
+
const TABLE_CAPTION_PROP = 'tableCaption';
|
|
14
|
+
exports.RequireTableCaption = utils_1.ESLintUtils.RuleCreator.withoutDocs({
|
|
15
|
+
create(context) {
|
|
16
|
+
return {
|
|
17
|
+
JSXOpeningElement(node) {
|
|
18
|
+
if (node.name.type !== 'JSXIdentifier') {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const component = node.name.name;
|
|
22
|
+
if (!TABLE_COMPONENTS.includes(component)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const hasTableCaption = node.attributes.some((attr) => attr.type === 'JSXAttribute' &&
|
|
26
|
+
attr.name.type === 'JSXIdentifier' &&
|
|
27
|
+
attr.name.name === TABLE_CAPTION_PROP);
|
|
28
|
+
if (!hasTableCaption) {
|
|
29
|
+
context.report({
|
|
30
|
+
node,
|
|
31
|
+
messageId: 'missingTableCaption',
|
|
32
|
+
data: { component }
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
defaultOptions: [],
|
|
39
|
+
meta: {
|
|
40
|
+
type: 'problem',
|
|
41
|
+
docs: {
|
|
42
|
+
description: `Ensure ${TABLE_COMPONENTS.join(', ')} have a \`${TABLE_CAPTION_PROP}\` prop for accessibility.`,
|
|
43
|
+
},
|
|
44
|
+
schema: [],
|
|
45
|
+
messages: {
|
|
46
|
+
missingTableCaption: [
|
|
47
|
+
'{{component}} must include a `tableCaption` prop for accessibility.',
|
|
48
|
+
'',
|
|
49
|
+
'Example:',
|
|
50
|
+
' <{{component}} tableCaption="Descriptive caption for the table" ... />',
|
|
51
|
+
].join('\n'),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=require_table_caption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require_table_caption.js","sourceRoot":"","sources":["../../../../src/rules/a11y/require_table_caption.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,oDAAsE;AAEtE,MAAM,gBAAgB,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;AAC/D,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAE7B,QAAA,mBAAmB,GAAG,mBAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACrE,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,iBAAiB,CAAC,IAAgC;gBAChD,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;oBACvC,OAAO;gBACT,CAAC;gBAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAEjC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC1C,OAAO;gBACT,CAAC;gBAED,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAC1C,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,CAAC,IAAI,KAAK,cAAc;oBAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;oBAClC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,kBAAkB,CACxC,CAAC;gBAEF,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,qBAAqB;wBAChC,IAAI,EAAE,EAAE,SAAS,EAAE;qBACpB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IACD,cAAc,EAAE,EAAE;IAClB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,UAAU,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,kBAAkB,4BAA4B;SAC9G;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,mBAAmB,EAAE;gBACnB,qEAAqE;gBACrE,EAAE;gBACF,UAAU;gBACV,0EAA0E;aAC3E,CAAC,IAAI,CAAC,IAAI,CAAC;SACb;KACF;CACF,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elastic/eslint-plugin-eui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"typescript": "^5.8.3"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
|
-
"test": "
|
|
46
|
+
"test": "yarn test-unit",
|
|
47
|
+
"test-unit": "jest src",
|
|
47
48
|
"build": "yarn build:clean && yarn build:compile && yarn build:compile:esm && yarn build:types",
|
|
48
49
|
"build:clean": "rimraf lib/",
|
|
49
50
|
"build:compile:esm": "tsc --project ./tsconfig.esm.json",
|