meganrogge / template-string-converter

Autocorrect from quotes to backticks
MIT License
195 stars 24 forks source link

Conversion of React JSX Props on newlines fails #20

Open karlhorky opened 4 years ago

karlhorky commented 4 years ago

JSX props (React) on their own lines do not convert correctly to template strings:

function Div(props) {
  return (
    <div
      {...props}
      prop-on-new-line="abc"
      // comment
      another-on-new-line="def"
    />
  );
}

Kapture 2020-10-22 at 10 55 51

karlhorky commented 4 years ago

This is a known issue with the extension (see https://github.com/meganrogge/template-string-converter/issues/15#issuecomment-714446898 for background)

meganrogge commented 3 years ago

recording (78)

pushing this change soon after doing some more testing @karlhorky

karlhorky commented 3 years ago

Looks really good for this example @meganrogge , thanks!! 🙌

karlhorky commented 3 years ago

Another unhandled case is returning to the JavaScript rules once inside of JSX opening tags.

Inside of opening tags in JSX, there may be the use of JavaScript expressions (starting with an opening curly bracket and ending with a closing curly). Since we back in regular JavaScript, the special JSX opening tag rules / behavior should not apply.

One common example is usage of a style prop:

Kapture 2020-12-20 at 19 10 48

<Link
  to="/"
  style={{
    float: 'left',
  }}
>
  ←
</Link>

The result of editing 'left' here is float: {`left${}`}, should be float: `left${}`


Another example would be no prop at all, using object spread:

<Link
  {...{
    a: 'b'
  }}
/>

The result of editing 'b' here is a: {`b${}`}, should be a: `b${}`


Both of these examples with objects fail when editing values or also any keys which are in the form of strings (eg. editing display here: <Link style={{"display": "block"}} />).


Also, an expression as a standalone string (no usage of an object):

<Link
  href={'abc'}
/>

The result of editing 'abc' here is href={{`abc${}`}}, should be href={`abc${}`}


This also happens on single lines:

<Link href={'abc'} />

The result of editing 'abc' here is href={{`abc${}`}}, should be href={`abc${}`}


Or a different expression (an admittedly unusual pattern):

<Link
  href={href='abc'}
/>

The result of editing 'abc' here is href={href={`abc${}`}}, should be href={href=`abc${}`}


All of these fail when adding interpolation in the string.

New issue again?

meganrogge commented 3 years ago

@karlhorky thanks for the examples. reopened this issue and will look into it.

meganrogge commented 3 years ago

@karlhorky after re-reading this, I'm kind of confused. Are you saying in the example you provided it shouldn't convert to a JSX prop, even though it's following an = sign and is within a start and end tag? What is the difference here? Do you have a suggestion for how I can tell if it's within normal JavaScript instead of a JSX prop?

karlhorky commented 3 years ago

Sorry, I have updated the examples above to include what happens now and what should happen.

The main takeaway here can be the following rules:

  1. as soon as you hit <\w+\s+ (approximate, incomplete regex) in a JavaScript file, you're inside a JSX opening tag (and the special rules for props in JSX opening tags are activated)
  2. as soon as you hit { inside that tag, you are in a JavaScript expression, with normal JavaScript rules (until you hit a < again, recursively - which goes back to 1.)

The 1st rule above is being applied correctly, but the 2nd - going back to JavaScript rules within that opening tag - is not.

In case you're using regex, there are a couple of regular expression implementations for JSX opening tags and JavaScript expression in Prism.js and VS Code that may help:

meganrogge commented 3 years ago

Hoping to get to this soon

meganrogge commented 3 years ago

Having issues publishing the extension atm, but hopefully will be able to do so soon and thus reflect this fix.

karlhorky commented 3 years ago

Great! When there's a new version, I'll test it out :)

meganrogge commented 3 years ago

It has been released so lmk @karlhorky

karlhorky commented 3 years ago

ok trying on v0.5.4 now

karlhorky commented 3 years ago

The result of editing 'left' here is float: {`left${}`}, should be float: `left${}`

<Link
  to="/"
  style={{
    float: 'left',
  }}
>
  ←
</Link>

Hm, seems like this one is still open... Just tried in both a .tsx file and a .js file (both set as JavaScript and JavaScript (React) syntaxes)


didn't test the other cases yet in my comment above

meganrogge commented 3 years ago

Worked well for most of your examples when I tested it. Seems like there are a lot of cases to cover

karlhorky commented 3 years ago

Hm, interesting... for me, I haven't seen a single one that does work. Maybe the publish didn't work properly?

For example, here's another one that fails (which is a very common pattern in React code):

The result of editing 'abc' here is href={{`abc${}`}}, should be href={`abc${}`}

<Link href={'abc'} />

Should this issue be reopened? Or should I create a new issue with the content of my comment above?

meganrogge commented 3 years ago

feel free to make a PR @karlhorky i'm quite occupied working on vscode at the moment, so could take me awhile to get to this

karlhorky commented 2 years ago

In Template String Converter 0.5.8 it seems like there's a new bug which is causing extra curly braces to appear outside of JSX code (in a file with TypeScript React syntax):

https://user-images.githubusercontent.com/1935696/147680948-b533aadd-acd7-41b5-8e99-cd4267df9297.mp4

Opened https://github.com/meganrogge/template-string-converter/issues/61 for this.

meganrogge commented 2 years ago

I just noticed that in your original example, if you delete the comment line, it will work

meganrogge commented 2 years ago

that's a case I don't have time for at the moment, but about to push a fix for the other cases you mention in this issue.

Done

hunterwilhelm commented 2 weeks ago

For anyone here looking for what the setting was named:

Template string converter add brackets to props

or in your JSON

"template-string-converter.addBracketsToProps": true