djlint / djLint

✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang
https://djLint.com
GNU General Public License v3.0
664 stars 81 forks source link

[BUG] [Formatter] Shadowing built-in function breaks template #828

Open z64 opened 5 months ago

z64 commented 5 months ago

System Info

Issue

If the template shadows a built-in function, such as dir, it gets replaced in the template with invalid code that breaks the template.

How To Reproduce

Create a template file:

{% set dir = "example" %}
{% set foo = dir %}

Running djlint --reformat produces:

$ djlint --reformat test.html.j2

Reformatting 1/1 files

test.html.j2
@@ -1,2 +1,2 @@

 {% set dir = "example" %}
-{% set foo = dir %}
+{% set foo = <built-in function dir> %}

As in, the template's contents is now literally:

{% set dir = "example" %}
{% set foo = <built-in function dir> %}

Which will crash when evaluated.

FLiliequist commented 5 months ago

I’ve also encountered an similar issue when trying to format a set function. When trying to format {% set x = print(“Hello”) %} the result will be

Hello
{% set x = None %}

This behaviour suggests that the code after the equal sign is being executed as Python code, which I belive is unintended behaviour for a linter.

Upon reviewing the code quickly, I suspect that the bug comes from the usage of the eval function here indent.py. However, I’m not sure about purpose of the eval function here.

Maybe someone brighter than me can understand the eval statement?"

z64 commented 4 months ago

Hi @FLiliequist , thanks for those details. This seems to be the commit that introduced eval into this file:

https://github.com/djlint/djLint/commit/85aca4cf5dc368111e4e459d38c99beaae6fa3a5

for the purpose of formatting nodes that look like JSON5 or lists - it seems later commits might of increased the scope of where this code is executed so that now examples like yours & mine are now evaluated as well; seemingly for formatting functions / function parameters, etc.?

I'm not sure if its supposed to, but it seems like --no-function-formatting option doesn't fix this either.

FLiliequist commented 4 months ago

Nice finding :)

I have found a quick workaround for it, if I use the --no-set-formatting flag it wont try to format the {% set %}. Not a good solution but it doesn't break the code atleast :D

z64 commented 4 months ago

I have found a quick workaround for it, if I use the --no-set-formatting flag it wont try to format the {% set %}. Not a good solution but it doesn't break the code atleast :D

Ohhh I completely missed that. Thank you!

thedotedge commented 2 months ago

Is there a plan to fix this one? If JS or Twig templates are used, checking for Python functions doesn't make that much sense imo 😊

julientaq commented 21 hours ago

I have the same issue working with template that rely on the id of the object.

                {{ content |  addID(id) |  toc(tags=['h2']) | safe }}

becomes

                {{ content |  addID(<built-in function id>) |  toc(tags=['h2']) | safe }}

which breaks the layout.


i managed to get away by installing version 1.24.0