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 =
+test +
; +``` + ```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 =
+{imageDescription} +
; +``` + ```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: ` + blank image + ` } ), @@ -527,6 +536,14 @@ ruleTester.run('jsx-no-literals', rule, { errors: [ {message: stringsMessage('\'bar\'')} ] + }, + { + code: ` + blank image + `, + options: [{noAttributeStrings: true}], + errors: [ + {message: attributeMessage('\'blank image\'')}] } ] });