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

Add JSX prop alignment based on the first prop & between-prop space consistency #1729

Merged
merged 5 commits into from
May 16, 2018

Conversation

ThiefMaster
Copy link
Contributor

@ThiefMaster ThiefMaster commented Mar 19, 2018

This adds support for the JSX prop style suggested in #398 which is the default of the various JetBrains IDEs.
I haven't updated the docs yet since writing docs isn't fun so I'd rather know first that the PR has a chance of getting accepted before doing that.

Fixes #398.

// any space between the name and the first attribute
const afterNameLength = Math.max(1, firstPropNode.loc.start.column - node.name.loc.end.column);
if (afterNameLength !== 1) {
// this is not easily fixable, so we just report another error for it.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went for the lazy option here - the default fixing logic in report() cannot handle the case where the property isn't the first thing in the line and checkNodesIndent would need further changes as well.

If you think having an automated fixer for this is important I can have another look though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think it's very important to have an automated fixer for as many things as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I'll have another look at this

@@ -47,7 +47,7 @@ module.exports = {

schema: [{
oneOf: [{
enum: ['tab']
enum: ['tab', 'aligned']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aligned with what? opening tag, closing tag, first used prop name, tag name, etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any better suggestion? Naming is hard :p

My first idea was tag-aligned but jsx-closing-bracket-location usess that term with a different meaning, and just tag is too similar to tab IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it's aligned with the first prop?

What happens with:

<C a b c
   d
     e
       f
/>

Which is properly aligned, d, e, or f?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, d. So yeah, first-prop sounds actually a good name.

Just thinking.. should fixing double-space between tag and prop (the stuff from the other comment below) even be part of this rule or a completely new rule? In that case I'd look into creating such a rule and just remove the afterNameLength !== 1 error here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this rule should only cover prop indentation. I'm not sure what your specific question is tho, could you provide a code example?

Copy link
Contributor Author

@ThiefMaster ThiefMaster Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<Foo     bar>
-->
<Foo bar>

So this should then be handled by a separate rule (or is there already one which does that?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's not prop indentation - indentation is only "start of line + whitespace + thing"

// any space between the name and the first attribute
const afterNameLength = Math.max(1, firstPropNode.loc.start.column - node.name.loc.end.column);
if (afterNameLength !== 1) {
// this is not easily fixable, so we just report another error for it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think it's very important to have an automated fixer for as many things as possible.

@klimashkin
Copy link

Awesome!
Similar to eslint indent rule

indent: [2, 2, {
  'FunctionDeclaration': {
    'parameters': 'first',
    'body': 1,
  },
}]

we can call it first
'react/jsx-indent-props': [2, 'first']

@ThiefMaster
Copy link
Contributor Author

PR updated. Also removed a bunch of unused code from the rule in a separate commit (probably copy&paste from somewhere else).

@@ -29,11 +29,12 @@ firstName="John"

## Rule Options

It takes an option as the second parameter which can be `"tab"` for tab-based indentation or a positive number for space indentations.
It takes an option as the second parameter which can be `"tab"` for tab-based indentation, a positive number for space indentations or `"first"` for aligning the first attribute for each line with the tag's first attribute.
Note that using the `"first"` option allows very inconsistent indentation unless you also enable a rule that enforces the position of the first prop.
Copy link
Contributor Author

@ThiefMaster ThiefMaster Mar 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this rule does not exist yet; I'll add it to the PR later

@ThiefMaster
Copy link
Contributor Author

PR updated with the rule to deal with excessive spacing between tag/prop or props in the same line

@ThiefMaster ThiefMaster changed the title Support aligned indent for JSX props Add JSX prop alignment based on the first prop & between-prop space consistency Mar 21, 2018
*/
function report(node, needed, gotten, loc) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the loc no longer required because eslint gets it off the node?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was never provided when calling the function - probably just a copy&paste leftover from somewhere else.

@@ -0,0 +1,29 @@
# Disallow multiple spaces between inline JSX props
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure what this rule is, but please remove it from this PR :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the one I mentioned here: #1729 (comment)

I can move it to a separate PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh, ok. yes, thanks, a separate PR for it would be great.

@ThiefMaster
Copy link
Contributor Author

PR updated

ThiefMaster added a commit to indico/indico that referenced this pull request Apr 9, 2018
ThiefMaster added a commit to indico/indico that referenced this pull request May 7, 2018
ThiefMaster added a commit to indico/indico that referenced this pull request May 16, 2018
@ThiefMaster
Copy link
Contributor Author

Any chance to get it merged so it makes it into the next version?

@ljharb ljharb merged commit 0e9f1b1 into jsx-eslint:master May 16, 2018
@klimashkin
Copy link

Released in 7.9.0.
But seems like there is a conflict with eslint indent rule:

image

image

@ThiefMaster Is there a workaround for this? Probably i'm missing something in config

    'react/jsx-indent-props': [2, 'first'],
    'indent': [2, 2, {
      'SwitchCase': 1,
      'VariableDeclarator': {'var': 2, 'let': 2, 'const': 3},
      'outerIIFEBody': 1,
      'MemberExpression': 1,
      'FunctionDeclaration': {
        'parameters': 'first', 
        'body': 1, 
      },
      'FunctionExpression': {
        'parameters': 'first',
        'body': 1,
      },
      'CallExpression': {
        'arguments': 1,
      },
      'ArrayExpression': 1,
      'ObjectExpression': 1,
      'ImportDeclaration': 1,
      'flatTernaryExpressions': true,
      'ignoredNodes': [],
      'ignoreComments': false,
    }],

@ThiefMaster
Copy link
Contributor Author

ThiefMaster commented Jun 4, 2018

You have to exclude the JSX nodes from the indent rule:

  ignoredNodes:
    - JSXAttribute
    - JSXSpreadAttribute

@ThiefMaster ThiefMaster deleted the jsx-indent-props-aligned branch June 4, 2018 17:02
@klimashkin
Copy link

klimashkin commented Jun 4, 2018

@ThiefMaster Thank you for the quick response, that works!
Probably that should be added to the rule page

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants