rtts / djhtml

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

Backticks in multi-line js template literal strings cause ValueError #11

Closed jacklinke closed 3 years ago

jacklinke commented 3 years ago

Backticked multi-line JS template literals cause DjHTML to trip.

For instance, the following example:

{% extends "base.html" %}

{% load static i18n %}
{% block content %}
    <div class="row">
        Something here
    </div>
{% endblock content %}

{% block js %}
    <script>

        const format_duration_value = (a) => {
            let secs = a * 3600;  // get total amount of seconds from your input
            const days = Math.floor(secs / (3600 * 24));
            return (`
                <div class="form-inline text-nowrap text-center">
                    ${days.toString().padStart(2,'0')}
                    <small>m</small>
                </div>
            `);
        };

    </script>
{% endblock js %}

Causes this output:

❯  djhtml test.html 
Traceback (most recent call last):
  File "/home/jack/.local/bin/djhtml", line 8, in <module>
    sys.exit(main())
  File "/home/jack/.local/lib/python3.9/site-packages/djhtml/__main__.py", line 59, in main
    result = DjHTML(input_file.read()).indent(args.tabwidth)
  File "/home/jack/.local/lib/python3.9/site-packages/djhtml/modes.py", line 67, in indent
    lines = self.tokenize(tabwidth, level)
  File "/home/jack/.local/lib/python3.9/site-packages/djhtml/modes.py", line 89, in tokenize
    token.mode(token.text).indent(tabwidth, line.level).rstrip("\n")
  File "/home/jack/.local/lib/python3.9/site-packages/djhtml/modes.py", line 293, in indent
    lines = self.tokenize(tabwidth, level)
  File "/home/jack/.local/lib/python3.9/site-packages/djhtml/modes.py", line 83, in tokenize
    for token in self.create_tokens(raw_token):
  File "/home/jack/.local/lib/python3.9/site-packages/djhtml/modes.py", line 111, in create_tokens
    head, body, tail = filter(bool, re.split(r"(^.*)\n|\n(.*$)", raw_token))
ValueError: not enough values to unpack (expected 3, got 2)

If I simply remove the function return, it works as expected.

Likewise, a single-line string like this works fine:

{% extends "base.html" %}

{% load static i18n %}
{% block content %}
    <div class="row">
        Something here
    </div>
{% endblock content %}

{% block js %}
    <script>

        const format_duration_value = (a) => {
            let secs = a * 3600;  // get total amount of seconds from your input
            const days = Math.floor(secs / (3600 * 24));
            return (`<div class="form-inline text-nowrap text-center">${days.toString().padStart(2,'0')}<small>m</small></div>`);
        };

    </script>
{% endblock js %}
JaapJoris commented 3 years ago

Thank you for reporting this issue. The error was caused by my foolish way of splitting a string into head, body, and tail. I have fixed the bug and I have greatly improved the indenting algorithm in the latest version of DjHTML. I have included your code sample in the tests and as you can see the multiline template literal is now rendered correctly without errors \o/