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

Rule proposal: require parens around jsx that lives on its own line #1207

Closed
rsolomon opened this issue May 18, 2017 · 12 comments
Closed

Rule proposal: require parens around jsx that lives on its own line #1207

rsolomon opened this issue May 18, 2017 · 12 comments

Comments

@rsolomon
Copy link
Contributor

rsolomon commented May 18, 2017

The title is not very eloquent, so I'll explain what I'm after by example.

Currently you can only require parens around multiline jsx. I'd also like to require parens around single-line jsx, but only when it lives on its own line. This is particularly useful when within an arrow function.

For example, the following would raise an error:

foo.map((bar, baz) => 
  <div>I'm on my own line!</div>
);

As would this:

const content = 
  <div>Hi there!</div>;

The following would not raise errors:

foo.map((bar, baz) => (
  <div>I'm on my own line!</div>
));
const content = (
  <div>Hi there!</div>;
);
const content = <div>Hi there!</div>;
@ljharb
Copy link
Member

ljharb commented May 19, 2017

I'd love to add this to the airbnb config, since this is precisely what our style guide requires.

I feel like this might be better as an option to jsx-wrap-multilines, but I could be convinced it should be a new rule.

@rsolomon
Copy link
Contributor Author

I agree that it belongs in jsx-wrap-multilines. Preference on option nomenclature?

@ljharb
Copy link
Member

ljharb commented May 20, 2017

There's four existing syntaxes: declaration, assignment, return, arrow - this could be a fifth. Maybe standalone?

@rsolomon
Copy link
Contributor Author

rsolomon commented May 20, 2017

Upon a bit deeper inspection, it looks like the rule doesn't enforce parenthesis on newlines even on multiline expressions. Ex:

var hello = () => (<div>
  <p>Hello</p>
</div>);

Is considered valid, even though I would prefer the linter force it to be:

var hello = () => (
  <div>
    <p>Hello</p>
  </div>
);

I am wondering if this may require 2 changes:

  1. A new rule or new option added to jsx-wrap-multilines that enforces newlines after the opening paren and before the closing paren of multiline jsx expressions.

  2. The aforementioned standalone rule, that would treat standalone single-line jsx expressions as multiline.

@ljharb
Copy link
Member

ljharb commented May 21, 2017

Those two changes sound good.

@VinSpee
Copy link

VinSpee commented Jun 17, 2017

I think this is likely related:

running --fix on this code:

const MediaName = ({ name }: MediaNameProps) =>
  <Media
    queries={{
      xs: {
        minWidth: '24em',
      },
      sm: {
        minWidth: '45em',
      },
    }}
  >
    {({ sm }) =>
      <div>
        {name}
      </div>
    }
  </Media>;

results in

const MediaName = ({ name }: MediaNameProps) =>
  (<Media
    queries={{
      xs: {
        minWidth: '24em',
      },
      sm: {
        minWidth: '45em',
      },
    }}
  >
    {({ sm }) =>
      (<div>
        {name}
      </div>)
    }
    </Media>);

when I would expect

const MediaName = ({ name }: MediaNameProps) => (
  <Media
    queries={{
      xs: {
        minWidth: '24em',
      },
      sm: {
        minWidth: '45em',
      },
    }}
  >
    {({ sm }) => (
      <div>
        {name}
      </div>
    )}
  </Media>
);

is this the responsibility of this rule?

@ljharb
Copy link
Member

ljharb commented Jun 17, 2017

I would also expect the latter.

Which rule is warning on it if you omit --fix?

@jseminck
Copy link
Contributor

jseminck commented Jul 5, 2017

While looking into: #1282 - I also ran into some of the issues mentioned above.

When fixing the following:

{myCondition && 
  <div>
    <p>Hello World</p>
  </div>
}

The current auto fixer would return:

{myCondition && 
  (<div>
    <p>Hello World</p>
  </div>)
}

Which IMHO looks rather ugly. And I could not find any other ESLint rule that would format this into what we want (see below). I did manage to write the fixer in a way that it returns this for this specific case, but the code is quite fragile and probably would need a good set of unit tests to confirm it works correctly in all cases.

{myCondition && (
  <div>
    <p>Hello World</p>
  </div>
)}

My initial fixer implementation:

function(fixer) {
  const rightNode = node.expression.right;
  return [
    fixer.insertTextAfterRange(sourceCode.getTokenBefore(rightNode).range, ' ('),
    fixer.insertTextBeforeRange(sourceCode.getLastToken(node).range, ')')
  ];
}

So in addition to the above ticket and the points mentioned in here, I think it's needed to take a deeper look into this rule and see if it can be made more useful!

@iddan
Copy link

iddan commented Jul 23, 2017

Is someone working on this? Because we use prettier-eslint all of our codebase is now with ugly braces

@jseminck
Copy link
Contributor

There's a PR for it.

@iddan
Copy link

iddan commented Jul 23, 2017

#1285 ?

@ljharb
Copy link
Member

ljharb commented Nov 18, 2017

It seems like #1475 covers this.

@ljharb ljharb closed this as completed Nov 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants