Skip to content

Commit 771a4f4

Browse files
committed
Initial commit for table-uses-caption.
1 parent 645bf16 commit 771a4f4

File tree

6 files changed

+127
-2
lines changed

6 files changed

+127
-2
lines changed

docs/rules/table-uses-caption.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# table-uses-caption

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"name": "eslint-plugin-jsx-a11y",
3+
34
"version": "0.4.2",
45
"description": "A static analysis linter of jsx and their accessibility with screen readers.",
56
"keywords": [

src/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ module.exports = {
99
'use-onblur-not-onchange': require('./rules/use-onblur-not-onchange'),
1010
'no-access-key': require('./rules/no-access-key'),
1111
'label-uses-for': require('./rules/label-uses-for'),
12-
'no-hash-href': require('./rules/no-hash-href')
12+
'no-hash-href': require('./rules/no-hash-href'),
13+
'table-uses-caption': require('./rules/table-uses-caption')
1314
},
1415
configs: {
1516
recommended: {
@@ -26,7 +27,8 @@ module.exports = {
2627
"jsx-a11y/use-onblur-not-onchange": 2,
2728
"jsx-a11y/no-access-key": 2,
2829
"jsx-a11y/label-uses-for": 2,
29-
"jsx-a11y/no-hash-href": 2
30+
"jsx-a11y/no-hash-href": 2,
31+
"jsx-a11y/table-uses-caption": 2
3032
}
3133
}
3234
}

src/rules/table-uses-caption.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @fileoverview Enforce table element has child of caption with value.
3+
* @author Ethan Cohen
4+
*/
5+
'use strict';
6+
7+
// ----------------------------------------------------------------------------
8+
// Rule Definition
9+
// ----------------------------------------------------------------------------
10+
11+
import hasChild from '../util/hasChild';
12+
13+
const errorMessage = type => `${type} elements must have a caption element as child to ` +
14+
`programatically associate captions for data tables.`;
15+
16+
module.exports = context => ({
17+
JSXOpeningElement: node => {
18+
const typeCheck = [ 'table' ].concat(context.options[0]);
19+
const nodeType = node.name.name;
20+
21+
// Only check 'table' elements and custom types.
22+
if (typeCheck.indexOf(nodeType) === -1) {
23+
return;
24+
}
25+
26+
const hasCaption = hasChild(node.parent.children, 'caption');
27+
28+
if (hasCaption === false) {
29+
context.report({
30+
node,
31+
message: errorMessage(nodeType)
32+
});
33+
}
34+
}
35+
});
36+
37+
module.exports.schema = [
38+
{
39+
"oneOf": [
40+
{ "type": "string" },
41+
{
42+
"type": "array",
43+
"items": {
44+
"type": "string"
45+
},
46+
"minItems": 1,
47+
"uniqueItems": true
48+
}
49+
]
50+
}
51+
];

src/util/hasChild.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
3+
/**
4+
* Returns the value of the child element or false, indicating the child element
5+
* is not present on the JSX opening element.
6+
*
7+
* This treats undefined values as missing props, as they will not be used for
8+
* rendering on elements that live closest to the DOM (pure html JSX elements).
9+
*/
10+
const hasChild = (children, target) => (
11+
children.some(child => child.openingElement.name.name === target && child.children.length > 0)
12+
);
13+
14+
export default hasChild;

tests/src/rules/table-uses-caption.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* @fileoverview Enforce table element has child of caption with value.
3+
* @author Ethan Cohen
4+
*/
5+
6+
'use strict';
7+
8+
// -----------------------------------------------------------------------------
9+
// Requirements
10+
// -----------------------------------------------------------------------------
11+
12+
import rule from '../../../src/rules/table-uses-caption';
13+
import { RuleTester } from 'eslint';
14+
15+
const parserOptions = {
16+
ecmaVersion: 6,
17+
ecmaFeatures: {
18+
jsx: true
19+
}
20+
};
21+
22+
// -----------------------------------------------------------------------------
23+
// Tests
24+
// -----------------------------------------------------------------------------
25+
26+
const ruleTester = new RuleTester();
27+
28+
const expectedError = {
29+
message: `table elements must have a caption element as child to ` +
30+
`programatically associate captions for data tables.`,
31+
type: 'JSXOpeningElement'
32+
};
33+
34+
// const string = [ 'Avatar' ];
35+
// const array = [ [ 'Thumbnail', 'Image' ] ];
36+
37+
// const customError = type => ({
38+
// message: `${type} elements must have an alt tag.`,
39+
// type: 'JSXOpeningElement'
40+
// });
41+
42+
ruleTester.run('table-uses-caption', rule, {
43+
valid: [
44+
// DEFAULT ELEMENT 'table' TESTS
45+
{ code: '<table><caption>Cool data</caption></table>;', parserOptions },
46+
{ code: '<table><caption>`data of ${type}`</caption></table>;', parserOptions },
47+
{ code: '<table><caption><span>FOO</span></caption></table>;', parserOptions },
48+
{ code: '<table><th></th><tbody></tbody><caption><span>FOO</span></caption></table>;', parserOptions }
49+
],
50+
invalid: [
51+
{ code: '<table><caption></caption></table>;', errors: [ expectedError ], parserOptions },
52+
{ code: '<table></table>;', errors: [ expectedError ], parserOptions },
53+
{ code: '<table><Caption>abc</Caption></table>;', errors: [ expectedError ], parserOptions },
54+
{ code: '<table><th>1</th><tbody></tbody></table>;', errors: [ expectedError ], parserOptions }
55+
]
56+
});

0 commit comments

Comments
 (0)