Skip to content

Commit a2ab4ef

Browse files
author
Ethan Cohen
committed
Build out template literal strings to determine their value.
1 parent 27bad9b commit a2ab4ef

File tree

6 files changed

+46
-6
lines changed

6 files changed

+46
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eslint-plugin-jsx-a11y",
3-
"version": "0.2.2",
3+
"version": "0.2.3",
44
"description": "A static analysis linter of jsx and their accessibility with screen readers.",
55
"keywords": [
66
"eslint",

src/util/buildTemplateLiteral.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
/**
4+
* Returns the string value of a template literal object.
5+
* Tries to build it as best as it can based on the passed
6+
* prop. For instance `This is a ${prop}` will return 'This is a prop'.
7+
*
8+
* If the template literal builds to undefined (`${undefined}`), then
9+
* this should return undefined.
10+
*/
11+
const buildTemplateLiteral = templateLiteral => {
12+
const {
13+
quasis,
14+
expressions
15+
} = templateLiteral;
16+
const partitions = quasis.concat(expressions);
17+
18+
const rawString = partitions.sort((a, b) => a.start - b.start).reduce((raw, part) => {
19+
const {
20+
type
21+
} = part;
22+
if (type === 'TemplateElement') {
23+
return raw + part.value.raw;
24+
} else if (type === 'Identifier') {
25+
return raw + part.name;
26+
}
27+
28+
return raw;
29+
}, '');
30+
31+
return rawString === "undefined" ? undefined : rawString;
32+
};
33+
34+
export default buildTemplateLiteral;

src/util/getAttributeValue.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
import buildTemplateLiteral from './buildTemplateLiteral';
4+
35
/**
46
* Returns the value of a given attribute.
57
* Different types of attributes have their associated
@@ -14,16 +16,15 @@ const getAttributeValue = attribute => {
1416
} else if (attribute.type === 'JSXAttribute') {
1517

1618
if (attribute.value.type === 'Literal') {
17-
return attribute.value.value;
19+
return attribute.value.value === "" ? undefined : attribute.value.value;
1820
} else if (attribute.value.type === 'JSXExpressionContainer') {
1921
const expression = attribute.value.expression;
2022

2123
switch (expression.type) {
2224
case 'Literal':
23-
return expression.value;
25+
return expression.value === "" ? undefined : expression.value;
2426
case 'TemplateLiteral':
25-
// hot-fix before actually building out raw string value.
26-
return Boolean(expression.quasis) || Boolean(expression.expressions);
27+
return buildTemplateLiteral(expression);
2728
case 'Identifier':
2829
return expression.name == 'undefined' ? undefined : expression.name;
2930
case 'ArrowFunctionExpression':

tests/src/rules/img-uses-alt.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ ruleTester.run('img-uses-alt', rule, {
4949
invalid: [
5050
{ code: '<img />;', errors: [ expectedError ], parserOptions },
5151
{ code: '<img alt={undefined} />;', errors: [ expectedError ], parserOptions },
52+
{ code: '<img alt={`${undefined}`} />;', errors: [ expectedError ], parserOptions },
53+
{ code: '<img alt="" />;', errors: [ expectedError ], parserOptions },
5254
{ code: '<img src="xyz" />', errors: [ expectedError ], parserOptions },
5355
{ code: '<img {...this.props} />', errors: [ expectedError ], parserOptions }
5456
]

tests/src/rules/no-access-key.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ ruleTester.run('no-access-key', rule, {
3636
valid: [
3737
{ code: '<div />;', parserOptions },
3838
{ code: '<div {...props} />', parserOptions },
39-
{ code: '<div accessKey={undefined} />', parserOptions }
39+
{ code: '<div accessKey={undefined} />', parserOptions },
40+
{ code: '<div accessKey={`${undefined}`} />', parserOptions }
4041
],
4142
invalid: [
4243
{ code: '<div accesskey="h" />', errors: [ expectedError ], parserOptions },
@@ -45,6 +46,7 @@ ruleTester.run('no-access-key', rule, {
4546
{ code: '<div acCesSKeY="y" />', errors: [ expectedError ], parserOptions },
4647
{ code: '<div accessKey={"y"} />', errors: [ expectedError ], parserOptions },
4748
{ code: '<div accessKey={`${y}`} />', errors: [ expectedError ], parserOptions },
49+
{ code: '<div accessKey={`This is ${bad}`} />', errors: [ expectedError ], parserOptions },
4850
{ code: '<div accessKey={accessKey} />', errors: [ expectedError ], parserOptions }
4951
]
5052
});

tests/src/rules/use-label-for.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ ruleTester.run('use-label-for', rule, {
4545
invalid: [
4646
{ code: '<label id="foo" />', errors: [ expectedError ], parserOptions },
4747
{ code: '<label htmlFor={undefined} />', errors: [ expectedError ], parserOptions },
48+
{ code: '<label htmlFor={`${undefined}`} />', errors: [ expectedError ], parserOptions },
4849
{ code: '<label>First Name</label>', errors: [ expectedError ], parserOptions },
4950
{ code: '<label {...props}>Foo</label>', errors: [ expectedError ], parserOptions }
5051
]

0 commit comments

Comments
 (0)