1

How can I get ESLint indent to like this code:

const a = `
  <li
    style=${styleMap({
      color: '#F00',      // bad line
      background: '#0F0'  // bad line
    })}                   // bad line
  >Something</li>
`;

It doesn't like the indenting on the lines I marked bad line. This is what it wants me to do:

const a = `
  <li
    style=${styleMap({
  color: '#F00',
  background: '#0F0'
})}
  >
    <span>Something</span>
  </li>
`;

which looks ridiculous.

Here is my current rule regarding 'indent':

indent: ['error', 2, { SwitchCase: 1 }],

I looked through the indent documentation but didn't see anything that seemed to match this scenario.


Edit: I went through all of the options for the indent rule, set them all to 0 then went through one-by-one setting them to 10 to see which one affects my expression. Looks like ObjectExpression is the culprit, but that value is normally good.

It seems like there are some issue dealing with template literal multiple line placeholder object declarations. I think my only recourse is going to be to add it to ignoreNodes.

samanime
  • 25,408
  • 15
  • 90
  • 139
  • How about adding line-breaks after `${` and before the corresponding closing brace? – Andre Nuechter Apr 30 '20 at 18:37
  • @AndreNuechter Even doing that, it complains about everything between the `${` and closing `}` line as being too far. Wants me to shove those back so `styleMap(` lines up with the `const`. – samanime Apr 30 '20 at 19:06
  • I just tried that snippet in my IDE and I don't get any wild formatting-suggestions (I use almost the same eslint-rule). Is there maybe prettier or beautify in the mix? – Andre Nuechter Apr 30 '20 at 19:11
  • Nope. I'm running `eslint` from the command line directly on the raw JS. The only other thing is I am inheriting from the `google` config set, but I don't think ESLint does partial inheritance for a single rule, so I don't think that should come into play. – samanime Apr 30 '20 at 19:25

1 Answers1

1

Note: See the bottom of this answer for the final version. Tweaked it further as I continued through linting everything.

Once I narrowed it down a little further, I was able to find some better Google results and found this answer which seemed very similar to my problem, but not quite: Ignore the indentation in a template literal, with the ESLint `indent` rule

The AST pattern didn't work for my specific case (at least the first one). After poking it with an AST explorer, I ended up going with these patterns:

indent: ['error', 2, { 
  ignoredNodes: [
    'TemplateLiteral > CallExpression > ObjectExpression',
    'TemplateLiteral *'
  ]
]

The first covers the exact scenario in my question. The second covers a similar scenario:

const a = `
  <li
    style=${someFunc(
      'arg1',
      'arg2'
    })}      
  >Something</li>
`;

Seems this is ultimately an issue that ESLint is going to have to fix somehow, because the ObjectExpression check alone gets really confused inside of a template literal placeholder.


EDIT:

I changed the second expression from TemplateLiteral > CallExpression to TemplateLiteral > * because I found two more slightly different scenarios that weren't caught already. I'd prefer to be more specific, but I don't want to have to identify 80 different scenarios.


EDIT 2:

Changed TemplateLiteral > * to TemplateLiteral * instead because found even more that were nested and not caught by > *.

Now, the patterns are just one:

indent: ['error', 2, { 
  ignoredNodes: [
    'TemplateLiteral *'
  ]
]
samanime
  • 25,408
  • 15
  • 90
  • 139