diff --git a/CHANGELOG.md b/CHANGELOG.md
index 05fe8c8a30..cdd062b95b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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)
@@ -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
diff --git a/docs/rules/jsx-no-literals.md b/docs/rules/jsx-no-literals.md
index 06ba9a907c..56145e9d0c 100644
--- a/docs/rules/jsx-no-literals.md
+++ b/docs/rules/jsx-no-literals.md
@@ -26,16 +26,17 @@ var Hello =
## 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": [
, {"noStrings": true, "allowedStrings": ["allowed"], "ignoreProps": false}]
+"react/jsx-no-literals": [, {"noStrings": true, "allowedStrings": ["allowed"], "ignoreProps": false, "noAttributeStrings": true }]
```
In this configuration, the following are considered warnings:
@@ -54,6 +55,12 @@ var Hello =
;
```
+```jsx
+var Hello =
+
+
;
+```
+
```jsx
var Hello = ;
```
@@ -67,6 +74,7 @@ var Hello = ;
```
+
The following are **not** considered warnings:
```jsx
@@ -91,6 +99,13 @@ var Hello =
;
```
+```jsx
+// a string value stored within a variable used as an attribute's value
+var Hello =
+
+
;
+```
+
```jsx
// spread props object
var Hello =
diff --git a/lib/rules/jsx-no-literals.js b/lib/rules/jsx-no-literals.js
index c74ab82487..21ec54def4 100644
--- a/lib/rules/jsx-no-literals.js
+++ b/lib/rules/jsx-no-literals.js
@@ -40,6 +40,9 @@ module.exports = {
},
ignoreProps: {
type: 'boolean'
+ },
+ noAttributeStrings: {
+ type: 'boolean'
}
},
additionalProperties: false
@@ -47,16 +50,27 @@ module.exports = {
},
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,
@@ -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;
}
diff --git a/tests/lib/rules/jsx-no-literals.js b/tests/lib/rules/jsx-no-literals.js
index c06eec5994..70ca3c84d6 100644
--- a/tests/lib/rules/jsx-no-literals.js
+++ b/tests/lib/rules/jsx-no-literals.js
@@ -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, {
@@ -331,6 +335,11 @@ ruleTester.run('jsx-no-literals', rule, {
} `,
parser: parsers.BABEL_ESLINT,
options: [{noStrings: true, ignoreProps: false}]
+ },
+ {
+ code: `
+
+ `
}
),
@@ -527,6 +536,14 @@ ruleTester.run('jsx-no-literals', rule, {
errors: [
{message: stringsMessage('\'bar\'')}
]
+ },
+ {
+ code: `
+
+ `,
+ options: [{noAttributeStrings: true}],
+ errors: [
+ {message: attributeMessage('\'blank image\'')}]
}
]
});