mirror of
https://github.com/Hopiu/djLint.git
synced 2026-03-20 23:30:24 +00:00
feat(formatter): added option to add blank line before tags
closes #307
This commit is contained in:
parent
ee87ef7024
commit
b2bd1ea298
14 changed files with 205 additions and 5 deletions
|
|
@ -143,6 +143,24 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "blank_line_before_tag",
|
||||
"description": {
|
||||
"en": "Add an additional blank line before `{% <tag> ... %}` tag groups. Blank lines will never be added to start of file or between similar tags.",
|
||||
"ru": "Добавляет дополнительную пустую строку перед группами тегов `{% <tag> ... %}`. Пустые строки никогда не будут добавлены в начало файла или между похожими тегами.",
|
||||
"fr": "Ajoute une ligne blanche supplémentaire avant les groupes de balises `{% <tag> ... %}`. Les lignes vides ne seront jamais ajoutées au début du fichier ou entre des balises similaires."
|
||||
},
|
||||
"usage": [
|
||||
{
|
||||
"name": "pyproject.toml",
|
||||
"value": "blank_line_before_tag=\"load,extends,include\""
|
||||
},
|
||||
{
|
||||
"name": ".djlintrc",
|
||||
"value": "\"blank_line_before_tag\": \"load,extends,include\""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "profile",
|
||||
"description": {
|
||||
|
|
|
|||
|
|
@ -70,24 +70,43 @@ def condense_html(html: str, config: Config) -> str:
|
|||
)
|
||||
return True
|
||||
|
||||
def if_blank_line_before_match(config: Config, html: str) -> bool:
|
||||
"""Check if there should be a blank line before."""
|
||||
if config.blank_line_before_tag:
|
||||
return not any(
|
||||
re.findall(
|
||||
re.compile(
|
||||
rf"((?:{{%\s*?{tag}[^}}]+?%}}\n?)+)",
|
||||
re.IGNORECASE | re.MULTILINE | re.DOTALL,
|
||||
),
|
||||
html,
|
||||
)
|
||||
for tag in [x.strip() for x in config.blank_line_before_tag.split(",")]
|
||||
)
|
||||
return True
|
||||
|
||||
def condense_line(config: Config, match: re.Match) -> str:
|
||||
"""Put contents on a single line if below max line length."""
|
||||
if (
|
||||
len(match.group(1) + match.group(3) + match.group(4))
|
||||
< config.max_line_length
|
||||
) and if_blank_line_after_match(config, match.group(3)):
|
||||
(
|
||||
len(match.group(1) + match.group(3) + match.group(4))
|
||||
< config.max_line_length
|
||||
)
|
||||
and if_blank_line_after_match(config, match.group(3))
|
||||
and if_blank_line_before_match(config, match.group(3))
|
||||
):
|
||||
return match.group(1) + match.group(3) + match.group(4)
|
||||
|
||||
return match.group()
|
||||
|
||||
def add_blank_line(config: Config, html: str, match: re.Match) -> str:
|
||||
def add_blank_line_after(config: Config, html: str, match: re.Match) -> str:
|
||||
"""Add break after if not in ignored block."""
|
||||
if inside_ignored_block(config, html, match):
|
||||
return match.group()
|
||||
|
||||
return match.group() + "\n"
|
||||
|
||||
func = partial(add_blank_line, config, html)
|
||||
func = partial(add_blank_line_after, config, html)
|
||||
|
||||
# should we add blank lines after load tags?
|
||||
if config.blank_line_after_tag:
|
||||
|
|
@ -101,6 +120,27 @@ def condense_html(html: str, config: Config) -> str:
|
|||
html,
|
||||
)
|
||||
|
||||
def add_blank_line_before(config: Config, html: str, match: re.Match) -> str:
|
||||
"""Add break before if not in ignored block and not first line in file."""
|
||||
if inside_ignored_block(config, html, match) or match.start() == 0:
|
||||
return match.group()
|
||||
|
||||
return "\n" + match.group()
|
||||
|
||||
func = partial(add_blank_line_before, config, html)
|
||||
|
||||
# should we add blank lines before load tags?
|
||||
if config.blank_line_before_tag:
|
||||
for tag in [x.strip() for x in config.blank_line_before_tag.split(",")]:
|
||||
html = re.sub(
|
||||
re.compile(
|
||||
rf"(?<!^\n$)((?:{{%\s*?{tag}\b[^}}]+?%}}\n?)+)",
|
||||
re.IGNORECASE | re.MULTILINE | re.DOTALL,
|
||||
),
|
||||
func,
|
||||
html,
|
||||
)
|
||||
|
||||
func = partial(condense_line, config)
|
||||
|
||||
# put short single line tags on one line
|
||||
|
|
|
|||
|
|
@ -334,6 +334,11 @@ class Config:
|
|||
"blank_line_after_tag", None
|
||||
)
|
||||
|
||||
# add blank line before load tags
|
||||
self.blank_line_before_tag: Optional[str] = djlint_settings.get(
|
||||
"blank_line_before_tag", None
|
||||
)
|
||||
|
||||
# contents of tags will not be formatted
|
||||
self.ignored_block_opening: str = r"""
|
||||
<style
|
||||
|
|
|
|||
1
tests/test_config/test_blank_lines_before_tag/html.html
Normal file
1
tests/test_config/test_blank_lines_before_tag/html.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
{% extends "nothing.html" %}{% load stuff %}{% load stuff 2 %}{% include "html_two.html" %}<div></div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{% extends nothing %}
|
||||
|
||||
<div></div>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<tr>
|
||||
<td rowspan="{{ quality.row_span }}">
|
||||
|
||||
{% include "common/pdfs/partials/display_quality_improvements.html" %}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{% block this %}
|
||||
{% load i18n %}
|
||||
{% endblock this %}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{% blocktrans %}my words{% endblocktrans %}
|
||||
{% block body %}
|
||||
<div></div>
|
||||
|
||||
{% endblock body %}
|
||||
{% block js %}{% endblock %}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{% block include %}
|
||||
{# {% include 'common/sticky-topbar-hidden-nav.html' %}#}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<div class="tab-cnt">
|
||||
<div class="tab-dta active" id="details">
|
||||
<div class="em-grid">
|
||||
|
||||
{% include "pages/task/details_source.html.j2" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
{% load stuff %}
|
||||
<div></div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
[tool]
|
||||
[tool.djlint]
|
||||
blank_line_before_tag = "load, extends, include ,endblock "
|
||||
101
tests/test_config/test_blank_lines_before_tag/test_config.py
Normal file
101
tests/test_config/test_blank_lines_before_tag/test_config.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
"""Djlint tests specific to pyproject.toml configuration.
|
||||
|
||||
run::
|
||||
|
||||
pytest tests/test_config/test_blank_lines_before_tag/test_config.py --cov=src/djlint --cov-branch \
|
||||
--cov-report xml:coverage.xml --cov-report term-missing
|
||||
|
||||
for a single test, run::
|
||||
|
||||
pytest tests/test_config.py::test_custom_html --cov=src/djlint \
|
||||
--cov-branch --cov-report xml:coverage.xml --cov-report term-missing
|
||||
|
||||
"""
|
||||
# pylint: disable=C0116
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
from src.djlint import main as djlint
|
||||
|
||||
|
||||
def test_blank_lines_before_tag(runner: CliRunner) -> None:
|
||||
result = runner.invoke(
|
||||
djlint, ["tests/test_config/test_blank_lines_before_tag/html.html", "--check"]
|
||||
)
|
||||
|
||||
assert (
|
||||
"""+{% extends "nothing.html" %}
|
||||
+
|
||||
+{% load stuff %}
|
||||
+{% load stuff 2 %}
|
||||
+
|
||||
+{% include "html_two.html" %}
|
||||
+<div></div>"""
|
||||
in result.output
|
||||
)
|
||||
assert """1 file would be updated.""" in result.output
|
||||
assert result.exit_code == 1
|
||||
|
||||
result = runner.invoke(
|
||||
djlint,
|
||||
["tests/test_config/test_blank_lines_before_tag/html_two.html", "--check"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# check blocks that do not start on a newline - they should be left as is.
|
||||
result = runner.invoke(
|
||||
djlint,
|
||||
["tests/test_config/test_blank_lines_before_tag/html_three.html", "--check"],
|
||||
)
|
||||
|
||||
assert """0 files would be updated.""" in result.output
|
||||
assert result.exit_code == 0
|
||||
|
||||
result = runner.invoke(
|
||||
djlint,
|
||||
["tests/test_config/test_blank_lines_before_tag/html_four.html", "--check"],
|
||||
)
|
||||
|
||||
assert result.exit_code == 1
|
||||
assert (
|
||||
""" {% block this %}
|
||||
-{% load i18n %}
|
||||
+
|
||||
+ {% load i18n %}
|
||||
+
|
||||
{% endblock this %}
|
||||
"""
|
||||
in result.output
|
||||
)
|
||||
|
||||
# something perfect should stay perfect :)
|
||||
result = runner.invoke(
|
||||
djlint,
|
||||
["tests/test_config/test_blank_lines_before_tag/html_five.html", "--check"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# something perfect should stay perfect :)
|
||||
result = runner.invoke(
|
||||
djlint,
|
||||
["tests/test_config/test_blank_lines_before_tag/html_six.html", "--check"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# make sure endblock doesn't pick up endblocktrans :)
|
||||
result = runner.invoke(
|
||||
djlint,
|
||||
["tests/test_config/test_blank_lines_before_tag/html_seven.html", "--check"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# check that multiple blank lines are not added
|
||||
result = runner.invoke(
|
||||
djlint,
|
||||
[
|
||||
"tests/test_config/test_blank_lines_before_tag/html_eight.html",
|
||||
"--preserve-blank-lines",
|
||||
"--check",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
Loading…
Reference in a new issue