Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] jsx-no-literals: add noAttributeStrings option #2782

Merged
merged 1 commit into from Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
### Added
* [`button-has-type`]: support trivial ternary expressions ([#2748][] @Hypnosphi)
* [`jsx-handler-names`]: add `checkInlineFunction` option ([#2761][] @dididy)
* [`jsx-no-literals`]: add `noAttributeStrings` option ([#2782][] @TaLeaMonet)

### Fixed
* [`function-component-definition`]: ignore object properties ([#2771][] @stefan-wullems)
Expand All @@ -21,6 +22,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
[#2796]: https://github.com/yannickcr/eslint-plugin-react/pull/2796
[#2791]: https://github.com/yannickcr/eslint-plugin-react/pull/2791
[#2789]: https://github.com/yannickcr/eslint-plugin-react/pull/2789
[#2782]: https://github.com/yannickcr/eslint-plugin-react/pull/2782
[#2780]: https://github.com/yannickcr/eslint-plugin-react/pull/2780
[#2779]: https://github.com/yannickcr/eslint-plugin-react/pull/2779
[#2772]: https://github.com/yannickcr/eslint-plugin-react/pull/2772
Expand Down
19 changes: 17 additions & 2 deletions docs/rules/jsx-no-literals.md
Expand Up @@ -26,16 +26,17 @@ var Hello = <div>

## Rule Options

There are two options:
The supported options are:

* `noStrings` (default: `false`) - Enforces no string literals used as children, wrapped or unwrapped.
* `allowedStrings` - An array of unique string values that would otherwise warn, but will be ignored.
* `ignoreProps` (default: `false`) - When `true` the rule ignores literals used in props, wrapped or unwrapped.
* `noAttributeStrings` (default: `false`) - Enforces no string literals used in attributes when set to `true`.

To use, you can specify as follows:

```js
"react/jsx-no-literals": [<enabled>, {"noStrings": true, "allowedStrings": ["allowed"], "ignoreProps": false}]
"react/jsx-no-literals": [<enabled>, {"noStrings": true, "allowedStrings": ["allowed"], "ignoreProps": false, "noAttributeStrings": true }]
```

In this configuration, the following are considered warnings:
Expand All @@ -54,6 +55,12 @@ var Hello = <div>
</div>;
```

```jsx
var Hello = <div>
<img alt="test"> </img>
</div>;
```

```jsx
var Hello = <div class='xx' />;
```
Expand All @@ -67,6 +74,7 @@ var Hello = <div class={`xx`} />;
```



The following are **not** considered warnings:

```jsx
Expand All @@ -91,6 +99,13 @@ var Hello = <div>
</div>;
```

```jsx
// a string value stored within a variable used as an attribute's value
var Hello = <div>
<img alt={imageDescription} {...props} />
</div>;
```

```jsx
// spread props object
var Hello = <Text {...props} />
Expand Down
44 changes: 35 additions & 9 deletions lib/rules/jsx-no-literals.js
Expand Up @@ -40,23 +40,37 @@ module.exports = {
},
ignoreProps: {
type: 'boolean'
},
noAttributeStrings: {
type: 'boolean'
}
},
additionalProperties: false
}]
},

create(context) {
const defaults = {noStrings: false, allowedStrings: [], ignoreProps: false};
const defaults = {
noStrings: false,
allowedStrings: [],
ignoreProps: false,
noAttributeStrings: false
};
const config = Object.assign({}, defaults, context.options[0] || {});
config.allowedStrings = new Set(config.allowedStrings.map(trimIfString));

const message = config.noStrings
? 'Strings not allowed in JSX files'
: 'Missing JSX expression container around literal string';
function defaultMessage() {
if (config.noAttributeStrings) {
return 'Strings not allowed in attributes';
}
if (config.noStrings) {
return 'Strings not allowed in JSX files';
}
return 'Missing JSX expression container around literal string';
}

function reportLiteralNode(node, customMessage) {
const errorMessage = customMessage || message;
const errorMessage = customMessage || defaultMessage();

context.report({
node,
Expand All @@ -77,10 +91,22 @@ module.exports = {
return false;
}
const parent = getParentIgnoringBinaryExpressions(node);
const standard = !/^[\s]+$/.test(node.value)
&& typeof node.value === 'string'
&& parent.type.indexOf('JSX') !== -1
&& parent.type !== 'JSXAttribute';

function isParentNodeStandard() {
if (!/^[\s]+$/.test(node.value) && typeof node.value === 'string' && parent.type.includes('JSX')) {
if (config.noAttributeStrings) {
return parent.type === 'JSXAttribute';
}
if (!config.noAttributeStrings) {
return parent.type !== 'JSXAttribute';
}
}

return false;
}

const standard = isParentNodeStandard();

if (config.noStrings) {
return standard;
}
Expand Down
17 changes: 17 additions & 0 deletions tests/lib/rules/jsx-no-literals.js
Expand Up @@ -39,6 +39,10 @@ function invalidProp(str) {
return `Invalid prop value: “${str}”`;
}

function attributeMessage(str) {
return `Strings not allowed in attributes: “${str}”`;
}

const ruleTester = new RuleTester({parserOptions});
ruleTester.run('jsx-no-literals', rule, {

Expand Down Expand Up @@ -331,6 +335,11 @@ ruleTester.run('jsx-no-literals', rule, {
} `,
parser: parsers.BABEL_ESLINT,
options: [{noStrings: true, ignoreProps: false}]
},
{
code: `
<img alt='blank image'></img>
`
}
),

Expand Down Expand Up @@ -527,6 +536,14 @@ ruleTester.run('jsx-no-literals', rule, {
errors: [
{message: stringsMessage('\'bar\'')}
]
},
{
code: `
<img alt='blank image'></img>
`,
options: [{noAttributeStrings: true}],
errors: [
{message: attributeMessage('\'blank image\'')}]
}
]
});