HTML Template Linter and Formatter. Use with Django, Jinja, Nunjucks and Handlebars templates.

Overview

djLint Logo

Find common formatting issues and reformat HTML templates.

Django · Jinja · Nunjucks · Handlebars · Mustache · GoLang

Ps, --check it out on other templates as well!

codecov test Codacy Badge Maintainability Downloadschat PyPI

Documentation

Read the documentation

Installation and Usage

djLint can be installed with pip install djlint, and is easy to run:

" | djlint - ">
# to lint a directory
djlint /path

# to lint a directory with custom extension
djlint /path -e html.dj

# to check formatting on a file
djlint /path/file.html.j2 --check

# to reformt a directory without printing the file diff
djlint /path --reformat --quiet

# using stdin
echo "
   
"
| djlint -

Show your format

Add a badge to your projects readme.md:

[![Code style: djlint](https://img.shields.io/badge/html%20style-djlint-blue.svg)](https://github.com/Riverside-Healthcare/djlint)

Add a badge to your readme.rst:

.. image:: https://img.shields.io/badge/html%20style-djlint-blue.svg
   :target: https://github.com/Riverside-Healthcare/djlint

Looks like this:

djLint

Contributing

Send a pr with a new feature, or checkout the issue list and help where you can.

Comments
  • [BUG] [Formatter] IndexError: list index out of range

    [BUG] [Formatter] IndexError: list index out of range

    Thanks for useful tool!

    I understand that formatting is beta feature.

    Just a bug reporting.

    System Info

    • OS: e.g. ubuntu 20.04
    • Python Version 3.8
    • djLint Version (1.7.0)
    • template language: e.g. twig

    Issue

    --check and --reformat follows to Phyton exception in some twig files. But --lint passed ok these files.

    djlint view/admin/driver_form.html.twig --check --profile=nunjucks
    
    concurrent.futures.process._RemoteTraceback:                                                                                                                                                          
    """
    Traceback (most recent call last):
      File "/usr/lib/python3.8/concurrent/futures/process.py", line 239, in _process_worker
        r = call_item.fn(*call_item.args, **call_item.kwargs)
      File "/home/vladp/.local/lib/python3.8/site-packages/djlint/__init__.py", line 259, in process
        output["format_message"] = reformat_file(
    [problem_page.html.twig.txt](https://github.com/Riverside-Healthcare/djLint/files/9075293/problem_page.html.twig.txt)
    config, this_file)
      File "/home/vladp/.local/lib/python3.8/site-packages/djlint/reformat.py", line 23, in reformat_file
        indented = indent_html(condensed, config)
      File "/home/vladp/.local/lib/python3.8/site-packages/djlint/formatter/indent.py", line 183, in indent_html
        tmp = re.sub(
      File "/home/vladp/.local/lib/python3.8/site-packages/regex/regex.py", line 278, in sub
        return pat.sub(repl, string, count, pos, endpos, concurrent, timeout)
      File "/home/vladp/.local/lib/python3.8/site-packages/djlint/formatter/attributes.py", line 271, in format_attributes
        attributes = format_template_tags(config, attributes)
      File "/home/vladp/.local/lib/python3.8/site-packages/djlint/formatter/attributes.py", line 218, in format_template_tags
        attributes = add_indentation(config, attributes)
      File "/home/vladp/.local/lib/python3.8/site-packages/djlint/formatter/attributes.py", line 44, in add_indentation
        start_test = (
    IndexError: list index out of range
    """
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/home/vladp/.local/bin/djlint", line 8, in <module>
        sys.exit(main())
      File "/home/vladp/.local/lib/python3.8/site-packages/click/core.py", line 1130, in __call__
        return self.main(*args, **kwargs)
      File "/home/vladp/.local/lib/python3.8/site-packages/click/core.py", line 1055, in main
        rv = self.invoke(ctx)
      File "/home/vladp/.local/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/home/vladp/.local/lib/python3.8/site-packages/click/core.py", line 760, in invoke
        return __callback(*args, **kwargs)
      File "/usr/lib/python3.8/contextlib.py", line 75, in inner
        return func(*args, **kwds)
      File "/home/vladp/.local/lib/python3.8/site-packages/djlint/__init__.py", line 216, in main
        file_errors.append(future.result())
      File "/usr/lib/python3.8/concurrent/futures/_base.py", line 437, in result
        return self.__get_result()
      File "/usr/lib/python3.8/concurrent/futures/_base.py", line 389, in __get_result
        raise self._exception
    IndexError: list index out of range
    

    How To Reproduce

    problem file is attached problem_page.html.twig.txt

    :microbe: bug :sponge: formatter released 
    opened by palansher 30
  • [Question] Is there any plan to Linter integration for Editor/IDE?

    [Question] Is there any plan to Linter integration for Editor/IDE?

    Thanks for this tool. Do you have any plans for djlint as a linter to run from the Editor or IDE?

    Also, in that case, it might be good to have stdin support as well.

    Example:

    cat polls/templates/index.html | djlint --check  -
    
    :steam_locomotive: enhancement :question: question released 
    opened by yaegassy 19
  • Django: djLint changes {% blocktranslate %} if not using trimmed strings

    Django: djLint changes {% blocktranslate %} if not using trimmed strings

    This may or may not be a problem. I think I like the fact that {% blocktranslate %} tags are formatted as well, but without trimmed the original string changes each time the template is reindented and that's a bit bad.

    Maybe this is something to add, for example in a new recommendations section.

    need information released 
    opened by matthiask 17
  • Unstable formatter adds extra indentation on every execution

    Unstable formatter adds extra indentation on every execution

    The following sample was tested with v1.9.4 and 1.12.1 - both exhibit the same behaviour (project is running 1.9.4, and 1.12.1 is latest version at the time this issue is being raised)

    Issue #166 appears to be cover the same issue, but that is reported as fixed back in v1.0

    I have been through the documentation, and there appears to be no way to disable the DJLint formatter (the 'djlint:off' comment appears to only disable linting, not formatting?).

    The issue:

    I'm embedding some Jinja2 code inside a script block, and unfortunately the embedded Javascript formatter is butchering the code badly... so I've used the 'beautify preserve:start/end' pragmas to disable the javascript formatting... which works.

    However, when I disable the javascript formatting, the djlint formatter starts adding extra indentation on every execution.

    Sample code (entire contents of 'formatter_test.html.j2' file):

    {% macro generate_clear_script(ids) %}
        <script type="text/javascript">
        /* beautify preserve:start */
            function reset_adv_search_form() {
                {%- for id in ids %}
                $('#{{ id }}').val([]);
                $('#{{ id }} option').prop("selected", false);
                {%- endfor %}
                $('#from_date').val('');
            }
        /* beautify preserve:end */
        </script>
    {% endmacro %}
    

    After the first iteration:

    {% macro generate_clear_script(ids) %}
        <script type="text/javascript">
            /* beautify preserve:start */
                    function reset_adv_search_form() {
                        {%- for id in ids %}
                        $('#{{ id }}').val([]);
                        $('#{{ id }} option').prop("selected", false);
                        {%- endfor %}
                        $('#from_date').val('');
                    }
                /* beautify preserve:end */
        </script>
    {% endmacro %}
    

    After the second iteration:

    {% macro generate_clear_script(ids) %}
        <script type="text/javascript">
            /* beautify preserve:start */
                            function reset_adv_search_form() {
                                {%- for id in ids %}
                                $('#{{ id }}').val([]);
                                $('#{{ id }} option').prop("selected", false);
                                {%- endfor %}
                                $('#from_date').val('');
                            }
                        /* beautify preserve:end */
        </script>
    {% endmacro %}
    

    And third iteration:

    {% macro generate_clear_script(ids) %}
        <script type="text/javascript">
            /* beautify preserve:start */
                                    function reset_adv_search_form() {
                                        {%- for id in ids %}
                                        $('#{{ id }}').val([]);
                                        $('#{{ id }} option').prop("selected", false);
                                        {%- endfor %}
                                        $('#from_date').val('');
                                    }
                                /* beautify preserve:end */
        </script>
    {% endmacro %}
    

    I've tested this behaviour up to 15 iterations, at which point I stopped. Every iteration, the code ends up further and further indented.

    Note: Also tested the same code using 'djlint:off/on' comments - had no impact (same indenting behaviour observed). test code with djlint:off/on comments, for reference:

    {% macro generate_clear_script(ids) %}
        {# djlint:off #}
        <script type="text/javascript">
        /* beautify preserve:start */
            function reset_adv_search_form() {
                {%- for id in ids %}
                $('#{{ id }}').val([]);
                $('#{{ id }} option').prop("selected", false);
                {%- endfor %}
                $('#from_date').val('');
            }
        /* beautify preserve:end */
        </script>
        {# djlint:on #}
    {% endmacro %}
    

    Current workaround: I've explicitly added the impacted file to the exclusion list in the .djlintrc file, but this is sub-optimal, as it means that none of the code in the file is validated as part of the CI/CD pipeline.

    released 
    opened by logicalChimp 15
  • [BUG] [Linter] Can't ignore H006

    [BUG] [Linter] Can't ignore H006

    System Info

    • OS: Archlinux
    • Python Version (3.10.6)
    • djLint Version (1.9.4)
    • template language: django

    Issue

    I'm not able to ignore H006 ('img tag should have height and width attributes.').

    How To Reproduce

    On pre-commit config use args: ["-i H006"] or use one of the methods provided on documentation

    :microbe: bug :mag: linter released 
    opened by aleprovencio 15
  • [BUG] [Linter] Error on empty html elements

    [BUG] [Linter] Error on empty html elements

    System Info

    • OS: Windows 10 Pro, Windows Server 2019 Standard
    • Python Version: 3.10.4, 3.8.8
    • djLint Version: 1.3.0
    • template language: html

    Issue

    Error on many html elements with no content, such as <br>, <p></p>, <h1></h1>, etc..

    Traceback:

    Traceback (most recent call last):
      File "C:\Python310\lib\runpy.py", line 196, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "C:\Python310\lib\runpy.py", line 86, in _run_code
        exec(code, run_globals)
      File "C:\Users\Kyanite\.virtualenvs\temp-Bh3UMC1v\Scripts\djlint.exe\__main__.py", line 7, in <module>
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\click\core.py", line 1130, in __call__
        return self.main(*args, **kwargs)
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\click\core.py", line 1055, in main
        rv = self.invoke(ctx)
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\click\core.py", line 1404, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\click\core.py", line 760, in invoke
        return __callback(*args, **kwargs)
      File "C:\Python310\lib\contextlib.py", line 79, in inner
        return func(*args, **kwds)
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\djlint\__init__.py", line 251, in main
        if bool(print_output(config, file_errors, len(file_list))) and config.warn is False:
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\djlint\output.py", line 34, in print_output
        lint_error_count += build_output(error["lint_message"], config)
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\djlint\output.py", line 91, in build_output
        echo(
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\click\utils.py", line 299, in echo
        file.write(out)  # type: ignore
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\colorama\ansitowin32.py", line 47, in write
        self.__convertor.write(text)
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\colorama\ansitowin32.py", line 170, in write
        self.write_and_convert(text)
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\colorama\ansitowin32.py", line 198, in write_and_convert
        self.write_plain_text(text, cursor, len(text))
      File "c:\users\kyanite\.virtualenvs\temp-bh3umc1v\lib\site-packages\colorama\ansitowin32.py", line 203, in write_plain_text
        self.wrapped.write(text[start:end])
      File "C:\Python310\lib\encodings\cp1252.py", line 19, in encode
        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
    UnicodeEncodeError: 'charmap' codec can't encode characters in position 39-117: character maps to <undefined>
    

    How To Reproduce

    A couple of examples where the error occurs:

    1. <p></p> error_example_1.txt
    2. <br> error_example_2.txt

    A couple of examples where the error does not occur:

    1. <p>a</p> success_example_1.txt
    2. <br/> success_example_2.txt
    :microbe: bug :mag: linter released 
    opened by lhuhmann 15
  • [BUG] [Formatter] <a> tags cause incorrect formatting

    [BUG] [Formatter] tags cause incorrect formatting

    System Info

    • OS: ubuntu 21.10
    • Python Version 3.9.7
    • djLint Version 0.7.4
    • template language: e.g. Jinja2

    Issue

    When reformatting a ".jinja2" html document, the indentation breaks after an <a> tag. I've observed this multiple times now.

    The code looks like this:

    How To Reproduce

    <a class="btn btn-primary"
     href="{{ url("url") }}"
     title="{{ _("Title") }}">
      <span class="iconify" data-icon="mdi:camera"></span> {{ _("Analyse your image!") }}</a>
    <div class="popup beautiful-popup" id="analysis-options">
      <h4>{{ _("Options") }}</h4> [...]
    </div>
    

    After reformatting it in VSCode using the djLint plugin, I obtain the following:

    <a class="btn btn-primary"
       href="{{ url("url") }}"
       title="{{ _("Title") }}">
      <span class="iconify" data-icon="mdi:camera"></span> {{ _("Analyse your image!") }}</a>
      <div class="popup beautiful-popup" id="analysis-options">
        <h4>{{ _("Options") }}</h4> [...]
      </div>
    

    So the <div>-Tag is incorrectly indented by one extra indentation level. And so is the rest of the document after that point!

    However, if I manually put the code in the following way (i.e. insert line breaks):

    <a class="btn btn-primary"
       href="{{ url("url") }}"
       title="{{ _("Title") }}">
        <span class="iconify" data-icon="mdi:camera"></span>
        {{ _("Analyse your image!") }}
        </a>
    <div class="popup beautiful-popup" id="analysis-options">
      <h4>{{ _("Options") }}</h4> [...]
    </div>
    

    then it will be correctly indented like so:

    <a class="btn btn-primary"
       href="{{ url("url") }}"
       title="{{ _("Title") }}">
      <span class="iconify" data-icon="mdi:camera"></span>
      {{ _("Analyse your image!") }}
    </a>
    <div class="popup beautiful-popup" id="analysis-options">
      <h4>{{ _("Options") }}</h4> [...]
    </div>
    

    I believe it is not related to the <a> tag but to some peculiar property with the {{}} tags or similar.

    The formatting should not be dependent on formatting in the initial document, as long as everything is valid xml, I think at least.

    :microbe: bug :sponge: formatter :toolbox: 2.0 
    opened by MrP01 13
  • Add require_pragma option

    Add require_pragma option

    This PR adds a configuration option for requiring files to have a pragma comment at the beginning of the file before reformatting the file. This behaviour is useful for a slow adoption of the tool instead of requiring the whole code base to be converted at once. It is inspired by the behaviour of prettier.

    Pull Request Check List

    Resolves: #issue-number-here

    • [ x ] Added tests for changed code.
    • [ x ] Updated documentation for changed code.
    released 
    opened by hrjakobsen 13
  • [FEATURE] Prevent text identation

    [FEATURE] Prevent text identation

    Feature Request

    The feature is to provide an option to prevent text being completely aligned when formatted. For example if I have this text:

    interface Ethernet1/2
      description // Connected to leaf-2
      no switchport
      ip address 10.1.2.1/30
      ip router ospf 1 area 0.0.0.0
      no shutdown
    
    interface Ethernet1/3
      description // Connected to leaf-3
      no switchport
      ip address 10.1.3.1/30
      ip router ospf 1 area 0.0.0.0
      no shutdown
    

    And I run the following I get all text aligned.

    ❯ djlint 1234  --profile=jinja --check
    
    Checking 1/1 files ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 00:01
    
    
    home/rick/1234
    ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    @@ -1,13 +1,12 @@
    
     interface Ethernet1/2
    -  description // Connected to leaf-2
    -  no switchport
    -  ip address 10.1.2.1/30
    -  ip router ospf 1 area 0.0.0.0
    -  no shutdown
    -
    +description // Connected to leaf-2
    +no switchport
    +ip address 10.1.2.1/30
    +ip router ospf 1 area 0.0.0.0
    +no shutdown
     interface Ethernet1/3
    -  description // Connected to leaf-3
    -  no switchport
    -  ip address 10.1.3.1/30
    -  ip router ospf 1 area 0.0.0.0
    -  no shutdown
    +description // Connected to leaf-3
    +no switchport
    +ip address 10.1.3.1/30
    +ip router ospf 1 area 0.0.0.0
    +no shutdown
    
    1 file would be updated.
    

    Ideally it would be good to have the option where the text is not aligned.

    Thanks,

    released 
    opened by rickdonato 10
  • Specify acceptable entities

    Specify acceptable entities

    Pull Request Check List

    Resolves: https://github.com/Riverside-Healthcare/djLint/issues/156

    • [x] Added tests for changed code.
    • [ ] Updated documentation for changed code.
    released 
    opened by jayvdb 10
  • [BUG] [Formatter]  endtag and closing tag on same line are adding whitespace

    [BUG] [Formatter] endtag and closing tag on same line are adding whitespace

    System Info

    • OS: Ubuntu 21.10
    • Python Version: 3.9.7
    • djLint Version: 0.7.1
    • template language: Django

    Issue

    Sometimes I'm seeing the formatter incorrect indent when two closing tags are right next to each other as shown in this diff:

    {% extends "base.html" %}
    -
     {% load i18n %}
     {% load account %}
    -
    -{% block head_title %}{% trans "Sign In" %}{% endblock %}
    -
    -{% block content %}
    -
    -<h1>{% trans "Sign In" %}</h1>
    -
    -<p>{% blocktrans %}If you have not created an account yet, then please
    -<a href="{{ signup_url }}">sign up</a> first.{% endblocktrans %}</p>
    -
    -<form class="login" method="POST" action="{% url 'account_login' %}">
    -  {% csrf_token %}
    -  {{ form.as_p }}
    -  {% if redirect_field_value %}
    -  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
    -  {% endif %}
    -  <a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>
    -  <button class="primaryAction" type="submit">{% trans "Sign In" %}</button>
    -</form>
    -
    +{% block head_title %}
    +    {% trans "Sign In" %}
     {% endblock %}
    +{% block content %}
    +    <h1>{% trans "Sign In" %}</h1>
    +    <p>
    +        {% blocktrans %}If you have not created an account yet, then please
    +            <a href="{{ signup_url }}">sign up</a> first.{% endblocktrans %}
    +        </p>
    +        <form class="login" method="POST" action="{% url 'account_login' %}">
    +            {% csrf_token %}
    +            {{ form.as_p }}
    +            {% if redirect_field_value %}
    +                <input type="hidden"
    +                       name="{{ redirect_field_name }}"
    +                       value="{{ redirect_field_value }}"/>
    +            {% endif %}
    +            <a class="button secondaryAction"
    +               href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>
    +            <button class="primaryAction" type="submit">{% trans "Sign In" %}</button>
    +        </form>
    +    {% endblock %}
    

    You can see the </p> and everything after, right after the endblocktrans, should be dedented one level

    How To Reproduce

    I see it every time I run the formatter against that specific template

    :microbe: bug :sponge: formatter 
    opened by gone 9
  • [BUG] [Formatter] Reformat on Windows causes files to be changed to CRLF line endings

    [BUG] [Formatter] Reformat on Windows causes files to be changed to CRLF line endings

    System Info

    • OS: Windows 10 (21H2)
    • Python Version (python --version): 3.10.8
    • djLint Version (djlint --version): 1.19.9
    • template language: nunjucks

    Issue

    When running djlint --reformat ., djLint notes that no files were updated, but on Windows all "formatted" files are changed from LF line endings to CRLF. When the same files are checked/linted (djlint --check --lint .), djLint finds no errors and notes no files would be updated.

    When running against the same files on Linux (I tested in a python:alpine container), the line endings are not changed.

    Normally I use VSCode with both the djLint and EditorConfig extensions configured for formatting on save, and in that case it appears the EditorConfig settings are applied last (so in my case the line endings are not changed since all are set to LF).

    For example:

    PS C:\test> djlint --check --lint .
    
    Checking and Linting 5/5 files »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»» 00:00     
    
    
    0 files would be updated.
    Linted 5 files, found 0 errors.
    
    PS C:\test> djlint --reformat .
    
    Reformatting 5/5 files »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»» 00:00     
    
    
    0 files were updated.
    

    But the 5 files were all changed from LF to CRLF.

    How To Reproduce

    Create a nunjucks file with LF line endings and run djlint --reformat ..

    Recommendations

    • I propose that ideally djLint wouldn't change the line endings of a file.
    • If djLint does intentionally change the line endings when reformatting:
      • The console output should reflect that changes were made
      • It would be helpful to have a configuration setting to either control the line endings or disable
      • The behavior should be documented
    :microbe: bug :sponge: formatter 
    opened by aarongoldenthal 3
  • [BUG] [Linter] Linter fails with D018 on data-action=

    [BUG] [Linter] Linter fails with D018 on data-action="xxx"

    System Info

    • OS: Mac OSX Ventura 13.1
    • Python Version (python --version): Python 3.11.1
    • djLint Version (djlint --version): djlint, version 1.19.10
    • template language: e.g. mustache: django

    Issue

    The Linter complains with an error D018 1:0 (Django) Internal links should use the {% url ... %} pattern. if a form has a data-action attribute.

    How To Reproduce

    Lint the following file:

    <form action="{% url 'something' %}" data-action="xxx"></form>
    

    Error: D018 1:0 (Django) Internal links should use the {% url ... %} pattern.

    This is an invalid error, the data-action parameter has nothing to do with URLs but is used in some web frameworks.

    This is happening due to the following error in the Regexp that checks for the D018 rule. The rule is currently the following: <form\s+?[^>]*?(?:action)=[\"|'](?!(?:https?://)|javascript:|on\w+:|mailto:|tel:)[\w|/]+ this does not enforce that there is a space before the action parameter. I'm suggesting that this line gets replaced with the following line: <form+?[^>]*?(?:\saction)=[\"|'](?!(?:https?://)|javascript:|on\w+:|mailto:|tel:)[\w|/]+

    This moves the requirement for the space into the "action" section and fixes this issue.

    :microbe: bug :mag: linter 
    opened by theomega 0
  • [BUG] [Linter] Linter complains about `data-action=

    [BUG] [Linter] Linter complains about `data-action="x"`

    System Info

    • OS: Mac OSX Ventura 13.1
    • Python Version (python --version): Python 3.11.1
    • djLint Version (djlint --version): djlint, version 1.19.10
    • template language: e.g. mustache: django

    Issue

    The Linter complains with an error D018 1:0 (Django) Internal links should use the {% url ... %} pattern. if a form has a data-action attribute.

    How To Reproduce

    Lint the following file:

    <form action="{% url 'something' %}" data-action="xxx"></form>
    

    Error: ``D018 1:0 (Django) Internal links should use the {% url ... %} pattern.```

    This is an invalid error, the data-action parameter has nothing to do with URLs but is used in some web frameworks.

    This is happening due to the following error in the Regexp that checks for the D018 rule. The rule is currently the following: <form\s+?[^>]*?(?:action)=[\"|'](?!(?:https?://)|javascript:|on\w+:|mailto:|tel:)[\w|/]+ this does not enforce that there is a space before the action parameter. I'm suggesting that this line gets replaced with the following line: <form+?[^>]*?(?:\saction)=[\"|'](?!(?:https?://)|javascript:|on\w+:|mailto:|tel:)[\w|/]+

    This moves the requirement for the space into the "action" section and fixes this issue.

    :microbe: bug :mag: linter 
    opened by theomega 0
  • [FEATURE] Multi-line classes

    [FEATURE] Multi-line classes

    Using tailwind in django templates, so there's a lot of classes. It's easier to keep them broken into several lines for easier readability.

    <a
      href="foo"
      class="
        inline-flex items-center p-4
        bg-white hover:bg-gray-200
        text-sm font-medium text-gray-500 hover:text-gray-700
      ">
    

    Currently djlint will want to put all of the classes into a single massive class string. Can we get a config rule to not remove class newlines?

    opened by TonisPiip 1
  • [BUG] [Formatter] django blocktranslate wrong indentation

    [BUG] [Formatter] django blocktranslate wrong indentation

    possible regression of #26

    djlint, version 1.19.7

    Issue

    Something is wrong with blocktranslate formatting, {% endblocktranslate %} is not properly indented.

    Code example - desired state

    <div>
        <span>
            {% translate "View all" %}
            <br />
            ({% blocktranslate count counter=images|length trimmed %}
                {{ counter }} photo
                {% plural %}
                {{ counter }} photos
            {% endblocktranslate %})
            <br/>
            <span>remark</span>
        </span>
    </div>
    

    Formatter output

    <div>
        <span>
            {% translate "View all" %}
            <br />
            ({% blocktranslate count counter=images|length trimmed %}
                {{ counter }} photo
                {% plural %}
                {{ counter }} photos
    {% endblocktranslate %})
            <br/>
            <span>remark</span>
        </span>
    </div>
    

    The example uses complex version of blocktranslate, but result is the same even if I remove count/trimmed args. Also wrapping content brackets (, ) ~~don't seem to play any role in this issue~~. see the comment

    Current workaround is to wrap all code in djlint:off.

    Thank you for djLint :green_heart:!


    :microbe: bug :sponge: formatter 
    opened by vasekch 3
  • [BUG] [Formatter] long textarea in twig - line wrapping does not work

    [BUG] [Formatter] long textarea in twig - line wrapping does not work

    Issue

    Your Djlint becomes better and better. Thank you!

    How To Reproduce

    I cannot reformat such long lines

    <textarea type="textarea" id="messageContent" name="adContent" maxlength="300" class="form-control" rows="10">{{ adContent|default }}</textarea>
    
    

    for like this:

    <textarea 
                   type="textarea" 
                   id="messageContent" 
                   name="adContent" 
                   maxlength="300"  
                   class="form-control" 
                   rows="10">
                   {{ adContent|default }}
    </textarea>
    

    It still one long line. Same time, the long 'inputs' and 'divs' are wrapped well.

    Please give your helping hand!


    BTW,

    By, according to my observations, for textareas

    this style

    <textarea 
                   content</textarea>
    

    is more prefferable then this

    <textarea 
                   content
    </textarea>
    

    Because in the second variant the browser adds extra ugly <CR/LF> trash to the end of content of textarea field. It happens when we have the combination of next three consistently: "content text" + line feed + "". So, the middle line feed makes the problem.


    my conf:

    .djlintrc

    {
        "ignore": "H021,H030,H031,H017,H023,H014,H006",
        "extension": "twig",
        "indent": "4",
        "profile": "nunjucks",
        "format_attribute_template_tags": false,
        "max_line_length": "110",
        "max_attribute_length": "100",
        "preserve_blank_lines": "true"
    }
    

    System Info

    • OS: e.g. ubuntu 20.04
    • Python Version 3.8.10
    • djLint Version 1.19.7
    • template language: twig
    :microbe: bug :sponge: formatter released 
    opened by palansher 14
Releases(v1.19.10)
Owner
Riverside Healthcare Analytics
Riverside Healthcare Analytics
HTML Template Linter and Formatter. Use with Django, Jinja, Nunjucks and Handlebars templates.

Find common formatting issues and reformat HTML templates. Django · Jinja · Nunjucks · Handlebars · Mustache · GoLang Ps, --check it out on other temp

Riverside Healthcare Analytics 263 Jan 01, 2023
✈️ HTML Template engine for python. Supports XSS preventation and many more!

Htmotor HTML Template Engine for Python! Installation: Open your terminal and type pip install htmotor.

Penguen 3 Nov 06, 2022
A simple, elegant Python based web templating engine (part of web.py).

Templator Simple, elegant Python based web templating (part of web.py). If you are familiar with Python, there is no new syntax to learn. This is a st

Dan 1 Dec 13, 2021
Template Render Engine

Template Render Engine Why TRender? It is just another template render engine so why should one choose TRender? TRender was originally created for Sir

Cesbit 18 Jul 30, 2022
A general purpose template driven code generator

💩 Shit Mountain Generator A general purpose template driven code generator Contribute shits to your company's shit mountain more efficiently! Quick S

Kelly 14 Mar 09, 2022
A string template language hosted by Python3 runtime

A string template language hosted by Python3 runtime. Conventionally, the source code of this language is written in plain text with utf-8 encoding and stored in a file with extension ".meme".

6 Nov 02, 2022
Mako Templates for Python

Mako Templates for Python Mako is a template library written in Python. It provides a familiar, non-XML syntax which compiles into Python modules for

mike bayer 173 Dec 22, 2022
Use a docx as a jinja2 template

Use a docx as a jinja2 template

Eric Lapouyade 1.4k Jan 02, 2023
Fast HTML/XML template engine for Python

Overview Chameleon is an HTML/XML template engine for Python. It uses the page templates language. You can use it in any Python web application with j

Malthe Borch 151 Dec 22, 2022
Simple reuse of partial HTML page templates in the Jinja template language for Python web frameworks.

Jinja Partials Simple reuse of partial HTML page templates in the Jinja template language for Python web frameworks. (There is also a Pyramid/Chameleo

Michael Kennedy 106 Dec 28, 2022
Mako Templates for Python

Mako Templates for Python Mako is a template library written in Python. It provides a familiar, non-XML syntax which compiles into Python modules for

SQLAlchemy 233 Dec 21, 2022