djLint icon indicating copy to clipboard operation
djLint copied to clipboard

[BUG] [Formatter] Attribute access after function calls in Jinja gets extra space

Open klette opened this issue 2 years ago • 6 comments

System Info

  • OS: Fedora 38
  • Python Version 3.11
  • djLint Version HEAD
  • template language: jinja

Issue

When function formatting is enabled the following template is formated wrongly breaking the template.

{{ foo('foo').bar }}

becomes

{{ foo("foo") .bar }}

The simple case of attribute access directly after the function call is easy enough to fix by adding \w to the \d in the "index" capture group (matching group 5).

Here with some comments on the regex added during testing the issue:

if config.no_function_formatting is False:
        func = partial(format_function, config, beautified_code)
        # format function contents
        beautified_code = re.sub(
            re.compile(
                r"""
                ([ ]*)    # Matching Group 1: Matches any number of spaces at the beginning
                ({{-?\+?) # Matching Group 2: Matches '{{' followed by an optional '-' or '+' sign
                [ ]*?     # Matches any number of spaces after '{{-?+' (non-greedy)
                ((?:(?!}}).)*?\w) # Matching Group 3: Matches any character except '}}' followed by a word character (\w)
                (\((?:\"[^\"]*\"|'[^']*'|[^\)])*?\)[ ]*)  # Matching Group 4: Matches parentheses and their contents within '{{...}}'
                ((?:\[[^\]]*?\]|\.[\d\w]+)[ ]*)? # Matching Group 5: Matches square brackets or dot notation within '{{...}}'
                ((?:(?!}}).)*?-?\+?}}) # Matching Group 6: Matches any character except '}}' followed by an optional '-' or '+' sign and '}}'
                """,
                flags=re.IGNORECASE | re.MULTILINE | re.VERBOSE | re.DOTALL,
            ),
            func,
            beautified_code,
        )

But the repeated case requires a bit more work to fix I think.

How To Reproduce

Add the following test cases to tests/test_jinja/test_parenthesis.py:

    pytest.param(
        ("{{ url('foo').foo }}"),
        ('{{ url("foo").foo }}\n'),
        id="function_call_attribute_access",
    ),
    pytest.param(
        ("{{ url('foo').foo().bar[1] }}"),
        ('{{ url("foo").foo().bar[1] }}\n'),
        id="function_call_attribute_access_multiple",
    ),

klette avatar Jun 30 '23 05:06 klette

Thanks for opening your first issue here!

welcome[bot] avatar Jun 30 '23 05:06 welcome[bot]

Thanks for reporting! You are welcome to do a pr with this, otherwise I will get it in a release next week.

christopherpickering avatar Jun 30 '23 12:06 christopherpickering

chained was pretty rough :D

christopherpickering avatar Jul 17 '23 16:07 christopherpickering

:tada: This issue has been resolved in version 1.32.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

christopherpickering avatar Jul 19 '23 02:07 christopherpickering

I don't have time to get to #720 in the next few days so I will roll back this change until then.

christopherpickering avatar Jul 20 '23 11:07 christopherpickering

I did leave in a fix for the extra spaces, even in chained functions, but only the first function will be formatted currently.

christopherpickering avatar Jul 20 '23 11:07 christopherpickering