Repository: yannickcr/eslint-plugin-react
Pull request #1718 (2018-03-09 22:33:20)

[fix] Allow whitespace jsx container in jsx-curly-brace-presence (fixes: #1717)
allows whitespace in JSX container in `react/jsx-curly-brace-presence` regardless of options. 
Potential fix for #1717  

cc. @pbondoer @ljharb 


Patch:
diff --git a/docs/rules/jsx-curly-brace-presence.md b/docs/rules/jsx-curly-brace-presence.md
index 00ba0e74..c4cd5ae6 100644
--- a/docs/rules/jsx-curly-brace-presence.md
+++ b/docs/rules/jsx-curly-brace-presence.md
@@ -139,12 +139,18 @@ will warned and fixed to:
 
 * If the rule is set to get rid of unnecessary curly braces(JSX expression) and there are characters that need to be escaped in its JSX form, such as quote characters, [forbidden JSX text characters](https://facebook.github.io/jsx/), escaped characters and anything that looks like HTML entity names, the code will not be warned because the fix may make the code less readable.
 
-The following pattern will **not** be given a warning even if `'never'` is passed.
+The following patterns will **not** be given a warning even if `'never'` is passed.
 
 ```jsx
 <Color text={"\u00a0"} />
 <App>{"Hello \u00b7 world"}</App>;
 <style type="text/css">{'.main { margin-top: 0; }'}</style>;
+/**
+ * there's no way to inject a whitespace into jsx without a container so this
+ * will always be allowed.
+ */
+<App>{' '}</App>
+<App>{'     '}</App>
 ```
 
 ## When Not To Use It
diff --git a/docs/rules/jsx-no-bind.md b/docs/rules/jsx-no-bind.md
index 686d1366..f6d3342c 100644
--- a/docs/rules/jsx-no-bind.md
+++ b/docs/rules/jsx-no-bind.md
@@ -121,8 +121,8 @@ Unfortunately [React ES6 classes](https://facebook.github.io/react/blog/2015/01/
 
 ```jsx
 class Foo extends React.Component {
-  constructor(...args) {
-    super(...args);
+  constructor() {
+    super();
     this._onClick = this._onClick.bind(this);
   }
   render() {
diff --git a/lib/rules/jsx-curly-brace-presence.js b/lib/rules/jsx-curly-brace-presence.js
index 15b00be5..27ba7fd5 100644
--- a/lib/rules/jsx-curly-brace-presence.js
+++ b/lib/rules/jsx-curly-brace-presence.js
@@ -99,6 +99,14 @@ module.exports = {
       );
     }
 
+    function containsWhitespaceExpression(child) {
+      if (child.type === 'JSXExpressionContainer') {
+        const value = child.expression.value;
+        return value ? !(/\S/.test(value)) : false;
+      }
+      return false;
+    }
+
     /**
      * Report and fix an unnecessary curly brace violation on a node
      * @param {ASTNode} node - The AST node with an unnecessary JSX expression
@@ -204,11 +212,27 @@ module.exports = {
         return false;
       }
 
+      if (
+        parent.children
+        && parent.children.length === 1
+        && containsWhitespaceExpression(parent.children[0])
+      ) {
+        return false;
+      }
+
       return areRuleConditionsSatisfied(parentType, config, OPTION_NEVER);
     }
 
-    function shouldCheckForMissingCurly(parentType, config) {
-      return areRuleConditionsSatisfied(parentType, config, OPTION_ALWAYS);
+    function shouldCheckForMissingCurly(parent, config) {
+      if (
+        parent.children
+        && parent.children.length === 1
+        && containsWhitespaceExpression(parent.children[0])
+      ) {
+        return false;
+      }
+
+      return areRuleConditionsSatisfied(parent.type, config, OPTION_ALWAYS);
     }
 
     // --------------------------------------------------------------------------
@@ -223,7 +247,7 @@ module.exports = {
       },
 
       Literal: node => {
-        if (shouldCheckForMissingCurly(node.parent.type, userConfig)) {
+        if (shouldCheckForMissingCurly(node.parent, userConfig)) {
           reportMissingCurly(node);
         }
       }


Test patch:
diff --git a/tests/lib/rules/jsx-curly-brace-presence.js b/tests/lib/rules/jsx-curly-brace-presence.js
index 959bf079..59d6563c 100644
--- a/tests/lib/rules/jsx-curly-brace-presence.js
+++ b/tests/lib/rules/jsx-curly-brace-presence.js
@@ -36,6 +36,32 @@ ruleTester.run('jsx-curly-brace-presence', rule, {
       code: '<App {...props}>foo</App>',
       options: [{props: 'never'}]
     },
+    /*
+     * There is no way to inject the space into JSX without an expression container
+     * so this format should always be allowed regardless of the `children` option.
+     */
+    {
+      code: '<App>{\' \'}</App>'
+    },
+    {
+      code: '<App>{\'     \'}</App>'
+    },
+    {
+      code: '<App>{\' \'}</App>',
+      options: [{children: 'never'}]
+    },
+    {
+      code: '<App>{\'    \'}</App>',
+      options: [{children: 'never'}]
+    },
+    {
+      code: '<App>{\' \'}</App>',
+      options: [{children: 'always'}]
+    },
+    {
+      code: '<App>{\'        \'}</App>',
+      options: [{children: 'always'}]
+    },
     {
       code: '<App {...props}>foo</App>',
       options: [{props: 'always'}]