Skip to content

Commit e866741

Browse files
thiagofelixljharb
authored andcommitted
[New] jsx-no-literals: new config for allowedProps
Fixes #3003
1 parent 9c5ac98 commit e866741

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

docs/rules/jsx-no-literals.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ The supported options are:
3333
- `noStrings` (default: `false`) - Enforces no string literals used as children, wrapped or unwrapped.
3434
- `allowedStrings` - An array of unique string values that would otherwise warn, but will be ignored.
3535
- `ignoreProps` (default: `false`) - When `true` the rule ignores literals used in props, wrapped or unwrapped.
36+
- `allowedProps` - An array of unique property names that would otherwise warn, but will be ignored.
3637
- `noAttributeStrings` (default: `false`) - Enforces no string literals used in attributes when set to `true`.
3738

3839
To use, you can specify as follows:
3940

4041
```js
41-
"react/jsx-no-literals": [<enabled>, {"noStrings": true, "allowedStrings": ["allowed"], "ignoreProps": false, "noAttributeStrings": true }]
42+
"react/jsx-no-literals": [<enabled>, {"noStrings": true, "allowedStrings": ["allowed"], "ignoreProps": false, "allowedProps": ["allowed"], "noAttributeStrings": true }]
4243
```
4344

4445
Examples of **incorrect** code for this rule, with the above configuration:
@@ -64,7 +65,7 @@ var Hello = <div>
6465
```
6566

6667
```jsx
67-
var Hello = <div class='xx' />;
68+
var Hello = <div class="xx" />;
6869
```
6970

7071
```jsx
@@ -116,6 +117,11 @@ var Hello = <Text {...props} />
116117
var Hello = <div class={xx} />
117118
```
118119

120+
```jsx
121+
// an allowed property
122+
var Hello = <div allowed="foo">allowed</div>
123+
```
124+
119125
```jsx
120126
// cache
121127
class Comp1 extends Component {

lib/rules/jsx-no-literals.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ module.exports = {
5151
ignoreProps: {
5252
type: 'boolean',
5353
},
54+
allowedProps: {
55+
type: 'array',
56+
uniqueItems: true,
57+
items: {
58+
type: 'string',
59+
},
60+
},
5461
noAttributeStrings: {
5562
type: 'boolean',
5663
},
@@ -63,11 +70,13 @@ module.exports = {
6370
const defaults = {
6471
noStrings: false,
6572
allowedStrings: [],
73+
allowedProps: [],
6674
ignoreProps: false,
6775
noAttributeStrings: false,
6876
};
6977
const config = Object.assign({}, defaults, context.options[0] || {});
7078
config.allowedStrings = new Set(config.allowedStrings.map(trimIfString));
79+
config.allowedProps = new Set(config.allowedProps.map(trimIfString));
7180

7281
function defaultMessageId() {
7382
const ancestorIsJSXElement = arguments.length >= 1 && arguments[0];
@@ -99,7 +108,8 @@ module.exports = {
99108
function isParentNodeStandard() {
100109
if (!/^[\s]+$/.test(node.value) && typeof node.value === 'string' && parent.type.includes('JSX')) {
101110
if (config.noAttributeStrings) {
102-
return parent.type === 'JSXAttribute' || parent.type === 'JSXElement';
111+
const isAllowedProp = parent.name && config.allowedProps.has(parent.name.name);
112+
return (parent.type === 'JSXAttribute' || parent.type === 'JSXElement') && !isAllowedProp;
103113
}
104114
if (!config.noAttributeStrings) {
105115
return parent.type !== 'JSXAttribute';
@@ -163,8 +173,9 @@ module.exports = {
163173

164174
JSXAttribute(node) {
165175
const isNodeValueString = node && node.value && node.value.type === 'Literal' && typeof node.value.value === 'string' && !config.allowedStrings.has(node.value.value);
176+
const isAllowedProp = config.allowedProps.has(node.name.name);
166177

167-
if (config.noStrings && !config.ignoreProps && isNodeValueString) {
178+
if (config.noStrings && !config.ignoreProps && isNodeValueString && !isAllowedProp) {
168179
const messageId = 'invalidPropValue';
169180
reportLiteralNode(node, messageId);
170181
}

tests/lib/rules/jsx-no-literals.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ ruleTester.run('jsx-no-literals', rule, {
281281
},
282282
{
283283
code: `
284-
<img alt='blank image'></img>
284+
<img alt="blank image"></img>
285285
`,
286286
},
287287
{
@@ -296,6 +296,23 @@ ruleTester.run('jsx-no-literals', rule, {
296296
`,
297297
options: [{ noStrings: true, allowedStrings: ['&mdash;', '—'] }],
298298
},
299+
{
300+
code: `
301+
<img alt="blank image"></img>
302+
`,
303+
options: [{ noStrings: true, allowedProps: ['alt'] }],
304+
},
305+
{
306+
code: `
307+
class Comp1 extends Component {
308+
asdf() {}
309+
render() {
310+
return <Foo bar={this.asdf} class="xx" />;
311+
}
312+
}
313+
`,
314+
options: [{ noStrings: true, allowedProps: ['class'] }],
315+
},
299316
]),
300317

301318
invalid: parsers.all([

0 commit comments

Comments
 (0)