rtts / djhtml

Django/Jinja template indenter
GNU General Public License v3.0
582 stars 32 forks source link

Excluding specific lines from being processed #17

Closed JaapJoris closed 3 years ago

JaapJoris commented 3 years ago

The errors that DjHTML spews out are often the result of mismatched Django and HTML tags, as in the following example:

{% if some_condition %}
    <a href="{% url some_url">
{% elif some_other_condition %}
    <a href="{% url some_other_url">
{% endif %}

[a bunch of details go here]

{% if end_tag_needed %}</a>{% endif %} 

I don’t consider this bad coding style, but it’s also impossible to correctly indent such code with an autoformatter. Perhaps DjHTML should offer a # fmt: off mechanism like Black does.

Such a tag would have to be placed inside a {# comment #} string so that it does not appear in the final output, and because Django comment strings are the only tags that are recognized in all modes. I propose to use the following "ignore" mechanism:

{# fmt: off #}
{% if some_condition %}
    <a href="{% url some_url">
{% elif some_other_condition %}
    <a href="{% url some_other_url">
{% endif %}

[a bunch of details go here]

{% if end_tag_needed %}</a>{% endif %} 
{# fmt: on #}

DjHTML should completely ignore whatever appears between these tags, but it is allowed to indent the begin and end tags.

JaapJoris commented 3 years ago

it’s impossible to correctly indent such code with an autoformatter

I disagree, the correct way to indent the example in this issue is given in the issue itself:

{% if some_condition %}
    <a href="{% url some_url">
{% elif some_other_condition %}
    <a href="{% url some_other_url">
{% endif %}

[a bunch of details go here]

{% if end_tag_needed %}</a>{% endif %} 

If we assume that Django template tags always have precedence, then the formatter could just indent the pieces in between "as best as it can", and reset the indentation as soon as the next Django tag is encountered:

{% block %}
    <a>
        <a>
            <a>
                <a>
                    <a>
{% endblock %}
{% for x in [1,2,3,4,5] %}
    </a>
{% endfor %}

In order to accomplish this, however, the current error message unclosed “<a>” on line 1 has to go. Actually, I think all error messages should go, given the goal stated in the readme:

The goal is to correctly indent already well-structured templates but not to fix broken ones.

This doesn't mean that a {# fmt:off #} tag wouldn't still be useful, though.