djLint icon indicating copy to clipboard operation
djLint copied to clipboard

[BUG] [Formatter] Some nested quotes inside Jinja tags are changed unnecessarily, leading to a VSCode error

Open dannypernik opened this issue 2 years ago • 25 comments

System Info

  • OS: Mac Ventura 13.0.1 (22A400)

  • Python Version:13.10.5

  • djLint Version 1.28.0

  • template language: Jinja

Issue

Single quotes nested inside jinja tags nested inside double quotes sometimes get converted to double quotes, which VSCode does not like: Screenshot 2023-05-19 at 4 07 19 PM

It would be wonderful if only nested quotes could be checked, alternating between single and double quotes as nesting deepens. This way, the top level quote preference could be preserved. (I'm sure there are some strong preferences for using single vs double quotes as the top level, often varying with filetype.)

How To Reproduce

Add the following line to VSCode and save: <a href="{{ url_for('test_reminders') }}" class="btn clr sm">Test reminders</a>

Thanks! 🤠

dannypernik avatar May 22 '23 17:05 dannypernik

Thanks for opening your first issue here!

welcome[bot] avatar May 22 '23 17:05 welcome[bot]

+1 for this, I'm facing the same issue. I've also added profile = "jinja" to my djlint config in pyproject.toml

geeshta avatar Jun 01 '23 11:06 geeshta

Thanks, I could use some logic help if anyone has time to check it out.

The functions are formatted with this code:

try:
            # try to format the contents as json
            data = json.loads(contents)
            contents = json.dumps(data, trailing_commas=False, ensure_ascii=False)

            if tag_size + len(contents) >= config.max_line_length:
                # if the line is too long we can indent the json
                contents = json.dumps(
                    data,
                    indent=config.indent_size,
                    trailing_commas=False,
                    ensure_ascii=False,
                )

        except:
            # was not json.. try to eval as set
            try:
                evaluated = str(eval(contents))
                # need to unwrap the eval
                contents = (
                    evaluated[1:-1]
                    if contents[:1] != "(" and evaluated[:1] == "("
                    else evaluated
                )
            except:
                contents = contents.strip()

        return (f"\n{leading_space}").join(contents.splitlines())

To get the quoting looking good (double > single > double > single etc) there are two possible ways:

  1. use existing quotes < here we would check the current outer quote and reuse it. Internal quotes we would leave to the formatters
  2. write some in depth code to check if we are in an attribute, and then iterate quotes from there

Currently I don't think djLint is changing any other quotes. image

It would be cool if we could tell json5 and eval not to touch quotes (eval we can probably specify since it is just python syntax)

Any ideas are appreciated :)

christopherpickering avatar Jun 01 '23 18:06 christopherpickering

@christopherpickering apologies for the extended delay. I don't have a full perspective of the implications of each option for nesting quotes, but option 1 (using existing quotes) seems simpler, so if that's sufficient to fix the issue, I'd go that route. It makes sense to leave the internal quotes to the formatters, which should prevent a breaking change.

Am I understanding correctly that user's preference of single or double quote for the outer quote will be preserved?

dannypernik avatar Jun 27 '23 14:06 dannypernik

I'm having this same issue. It causes syntax errors and won't allow routes to be used in flask. Has there been any progress on this or do you still need some assistance @christopherpickering?

For instance this here image is changed to image

If you are needing some assistance I might be able to do a PR here. Let me know, I'll take a look at this again tomorrow regardless.

jessielw avatar Jul 15 '23 05:07 jessielw

Thanks, a pr will be more than welcome 👍🏼

christopherpickering avatar Jul 15 '23 12:07 christopherpickering

Does is give a real flask error or just a vs code message?

christopherpickering avatar Jul 15 '23 12:07 christopherpickering

Does is give a real flask error or just a vs code message?

Rarely, but sometimes it'll add a white space in the inner quotes

"{{url_for(" home.home")}}"

Which will throw a flask error

jessielw avatar Jul 15 '23 15:07 jessielw

Dropped a PR request to fix both issues here

https://github.com/Riverside-Healthcare/djLint/pull/715

Note: this does not preserve the users quotes. It forces external quotes to be double and internal to be single.

I could make it go both ways though. Edit: I'm playing around with it to see if i can retain user outer quotes.

Edit 2: I spent a good few hours trying to accurately parse the users outer quotes and just replace the inner quotes. Not nearly as easy as I thought it would be. I almost got it working but not exactly how I wanted it. So ATM not pushing that.

jessielw avatar Jul 15 '23 23:07 jessielw

Update new code is stable, passes all tests, allows the linter to detect the outer most quotes and apply changes to the inner most to prevent vscode and syntax errors as well as handles spacing issues that can be caused by using the built in formatter in vscode and then using djlint.

jessielw avatar Jul 16 '23 22:07 jessielw

Checking in here

dannypernik avatar Aug 01 '23 16:08 dannypernik

@dannypernik for now you can install djlint from my repo with these changes (this is meant to be temporary until it's resolved here, but does work well I've been using it in production)

https://github.com/jlw4049/djLint/tree/jinja-formatting-issues

@christopherpickering and myself still hasn't had a change to sync up and work through some other things to put it on the main repo.

jessielw avatar Aug 01 '23 16:08 jessielw

@jlw4049 I had previously installed the VScode extension, so I'm not sure how to install from your fork.

dannypernik avatar Aug 08 '23 05:08 dannypernik

Hi @jlw4049!

I've just tested that your changes work perfectly!

Before: image

After: image

And they didn't explode anything else in the project :). Would love to see this merged!

vellvoid avatar Aug 28 '23 05:08 vellvoid

I'll see if I can't sync up with @christopherpickering this week so it can be added in properly

jessielw avatar Aug 28 '23 06:08 jessielw

@christopherpickering @jlw4049 Any updates? Thanks!

geeshta avatar Sep 23 '23 00:09 geeshta

@geeshta here is the PR here, I haven't worked on it to finish the required changes. I'll try to take some time and look into it tomorrow since I shouldn't be that busy.

https://github.com/Riverside-Healthcare/djLint/pull/715

jessielw avatar Sep 23 '23 03:09 jessielw

@jlw4049 @christopherpickering Checking in here

dannypernik avatar Oct 11 '23 04:10 dannypernik

I reached out to Christopher today once he responds back I'll spend some time getting this done

jessielw avatar Oct 11 '23 15:10 jessielw

I reached out to Christopher today once he responds back I'll spend some time getting this done

Hi, any news on this?

geeshta avatar Feb 11 '24 22:02 geeshta

I reached out to Christopher today once he responds back I'll spend some time getting this done

Hi, any news on this?

He did actually respond to me and I just never seen the notification. I am going to work on this more tomorrow. I left a response, this is a pretty complicated case and I'm not sure how we will handle it moving forward.

jessielw avatar Feb 12 '24 02:02 jessielw

I reached out to Christopher today once he responds back I'll spend some time getting this done

Hi, any news on this?

He did actually respond to me and I just never seen the notification. I am going to work on this more tomorrow. I left a response, this is a pretty complicated case and I'm not sure how we will handle it moving forward.

Very simple example is this:

<html>
  <head>
    <title>Test</title>
  </head>
  <body>
    <a href="{{ url_for('test') }}">Test</a>
  </body>
</html>

DJlint would turn the inner single quotes around 'test' to double quotes. It still runs but it's not desired, I prefer to alter single and double quotes for nested quotes and VS Code sees this as syntax error.

geeshta avatar Feb 14 '24 09:02 geeshta

Any updates?

dakixr avatar Aug 24 '24 14:08 dakixr