Skip to content

Commit

Permalink
Merge pull request #632 from Riverside-Healthcare/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
christopherpickering authored May 9, 2023
2 parents 3b6b337 + 234253d commit c3ef7c0
Show file tree
Hide file tree
Showing 13 changed files with 668 additions and 311 deletions.
23 changes: 23 additions & 0 deletions docs/src/_data/configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,29 @@
}
]
},
{
"name": "line_break_after_multiline_tag",
"tags": ["formatter"],
"description": {
"en": "Do not condense the content of multi-line tags into the line of the last attribute.",
"ru": "Не сжимайте содержимое многострочных тегов в строку последнего атрибута.",
"fr": "Ne pas condenser le contenu des balises multilignes dans la ligne du dernier attribut."
},
"usage": [
{
"name": "pyproject.toml",
"value": "line_break_after_multiline_tag=true"
},
{
"name": ".djlintrc",
"value": "\"line_break_after_multiline_tag\": \"true\""
},
{
"name": "cli",
"value": "--line-break-after-multiline-tag"
}
]
},
{
"name": "profile",
"tags": ["linter", "formatter"],
Expand Down
7 changes: 7 additions & 0 deletions src/djlint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@
default="",
help="Add an additional blank line before {% <tag> ... %} tag groups.",
)
@click.option(
"--line-break-after-multiline-tag",
is_flag=True,
help="Do not condense the content of multi-line tags into the line of the last attribute.",
)
@click.option(
"--custom-blocks",
type=str,
Expand Down Expand Up @@ -252,6 +257,7 @@ def main(
ignore_blocks: str,
blank_line_after_tag: str,
blank_line_before_tag: str,
line_break_after_multiline_tag: bool,
custom_blocks: str,
custom_html: str,
exclude: str,
Expand Down Expand Up @@ -290,6 +296,7 @@ def main(
ignore_blocks=ignore_blocks,
blank_line_after_tag=blank_line_after_tag,
blank_line_before_tag=blank_line_before_tag,
line_break_after_multiline_tag=line_break_after_multiline_tag,
custom_blocks=custom_blocks,
custom_html=custom_html,
exclude=exclude,
Expand Down
13 changes: 9 additions & 4 deletions src/djlint/formatter/condense.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,17 @@ def condense_html(html, config):

def condense_line(config: Config, html: str, match: re.Match) -> str:
"""Put contents on a single line if below max line length."""
# match.group(1) contains the opening tag, which may be split over multiple lines
if config.line_break_after_multiline_tag:
combined_length = len(match.group(1) + match.group(3) + match.group(4))
else:
combined_length = len(
match.group(1).splitlines()[-1] + match.group(3) + match.group(4)
)

if (
not inside_ignored_block(config, html, match)
and (
len(match.group(1).splitlines()[-1] + match.group(3) + match.group(4))
< config.max_line_length
)
and combined_length < config.max_line_length
and if_blank_line_after_match(config, match.group(3))
and if_blank_line_before_match(config, match.group(3))
):
Expand Down
2 changes: 1 addition & 1 deletion src/djlint/formatter/expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def add_html_line(out_format: str, match: re.Match) -> str:
Do not add whitespace if the tag is in a non indent block.
Do not add whiatespace if the tag is a in a template block
Do not add whitespace if the tag is a in a template block
"""
if inside_ignored_block(config, html, match):
return match.group(1)
Expand Down
2 changes: 1 addition & 1 deletion src/djlint/rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,4 @@
message: Duplicate attribute found.
flags: re.I
patterns:
- <\w[^>]*?\s([a-z][a-z-]*?)(?==.+?\1=[^>]*?>)
- <\w[^>]*?\s\K([a-z][a-z-]*?)(?==[^>]+?\1=[^>]*?>)
7 changes: 7 additions & 0 deletions src/djlint/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ def __init__(
custom_blocks: str = "",
blank_line_after_tag: str = "",
blank_line_before_tag: str = "",
line_break_after_multiline_tag: bool = False,
custom_html: str = "",
exclude: str = "",
extend_exclude: str = "",
Expand Down Expand Up @@ -435,6 +436,12 @@ def __init__(
str
] = blank_line_before_tag or djlint_settings.get("blank_line_before_tag", None)

# add line break after multi-line tags
self.line_break_after_multiline_tag: bool = (
line_break_after_multiline_tag
or djlint_settings.get("line_break_after_multiline_tag", False)
)

# contents of tags will not be formatted
self.ignored_block_opening: str = r"""
<style
Expand Down
55 changes: 20 additions & 35 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,24 +134,17 @@ def printer(expected, source, actual):
print(f"{ color.get(diff[:1], Style.RESET_ALL)}{diff}{Style.RESET_ALL}")


def lint_printer(source, expected, excluded, actual):
def lint_printer(source, expected, actual):
width, _ = shutil.get_terminal_size()

expected_text = "Expected Rules"
excluded_text = "Excluded Rules"
actual_text = "Actual"
source_text = "Source"

expected_width = int((width - len(expected_text) - 2) / 2)
excluded_width = int((width - len(excluded_text) - 2) / 2)
actual_width = int((width - len(actual_text) - 2) / 2)
source_width = int((width - len(source_text) - 2) / 2)

def padder(value, width):
if len(value) < width:
return str(value) + " " * (width - len(value))
return value[:20]

print()
print(
f"{Fore.BLUE}{Style.BRIGHT}{'─' * source_width} {source_text} {'─' * source_width}{Style.RESET_ALL}"
Expand All @@ -160,42 +153,34 @@ def padder(value, width):
print(source)
print()

if expected != ():
print(
f"{Fore.BLUE}{Style.BRIGHT}{'─' * expected_width} {expected_text} {'─' * expected_width}{Style.RESET_ALL}"
)
print()
for x in expected:
if isinstance(x, tuple):
print(f"{x[0]}, line #{x[1]}")
else:
print(x)
print()
if excluded != ():
print(
f"{Fore.BLUE}{Style.BRIGHT}{'─' * expected_width} {expected_text} {'─' * expected_width}{Style.RESET_ALL}"
)
print()
for x in expected:
print(
f"{Fore.BLUE}{Style.BRIGHT}{'─' * excluded_width} {excluded_text} {'─' * excluded_width}{Style.RESET_ALL}"
f"{Fore.RED}{Style.BRIGHT}{x['code']}{Style.RESET_ALL} {x['line']} {x['match']}"
)
print(f' {x["message"]}')
print()
for x in excluded:
if isinstance(x, tuple):
print(f"{x[0]}, line #{x[1]}")
else:
print(x)
print()

print(
f"{Fore.BLUE}{Style.BRIGHT}{'─' * actual_width} {actual_text} {'─' * actual_width}{Style.RESET_ALL}"
)
print()

if actual:
max_code = max(len(x["code"]) for x in actual)
max_line = max(len(x["line"]) for x in actual)
max_match = min(max(len(x["match"]) for x in actual), 20)
for x in actual:
print(
f'{padder(x["code"],max_code)} {padder(x["line"], max_line)} {padder(x["match"],max_match)} >> {x["message"]}'
)
for x in actual:
print(
f"{Fore.RED}{Style.BRIGHT}{x['code']}{Style.RESET_ALL} {x['line']} {x['match']}"
)
print(f' {x["message"]}')
print()
if len(actual) == 0:
print(f"{Fore.YELLOW}No codes found.{Style.RESET_ALL}")
print()

else:
print(f"{Fore.YELLOW}{actual}{Style.RESET_ALL}")
print()


Expand Down
95 changes: 95 additions & 0 deletions tests/test_html/test_line_break_after_multiline_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""Tests html details/summary tag.
poetry run pytest tests/test_html/test_tag_details_summary.py
"""
import pytest

from src.djlint.reformat import formatter
from tests.conftest import config_builder, printer

test_data = [
pytest.param(
(
'<div attribute="value" attributea="value" attributeb="value" attributec="value" attributed="value" attributef="value">string</div>\n'
),
(
'<div attribute="value"\n'
' attributea="value"\n'
' attributeb="value"\n'
' attributec="value"\n'
' attributed="value"\n'
' attributef="value">string</div>\n'
),
({}),
id="no_line_break_after_multiline_tag",
),
pytest.param(
(
'<div attribute="value"\n'
' attributea="value"\n'
' attributeb="value"\n'
' attributec="value"\n'
' attributed="value"\n'
' attributef="value">\n'
" string\n"
"</div>\n"
),
(
'<div attribute="value"\n'
' attributea="value"\n'
' attributeb="value"\n'
' attributec="value"\n'
' attributed="value"\n'
' attributef="value">string</div>\n'
),
({}),
id="no_line_break_after_multiline_tag_when_already_split",
),
pytest.param(
(
'<div attribute="value" attributea="value" attributeb="value" attributec="value" attributed="value" attributef="value">string</div>\n'
),
(
'<div attribute="value"\n'
' attributea="value"\n'
' attributeb="value"\n'
' attributec="value"\n'
' attributed="value"\n'
' attributef="value">\n'
" string\n"
"</div>\n"
),
({"line_break_after_multiline_tag": True}),
id="line_break_after_multiline_tag",
),
pytest.param(
(
'<div attribute="value"\n'
' attributea="value"\n'
' attributeb="value"\n'
' attributec="value"\n'
' attributed="value"\n'
' attributef="value">string</div>\n'
),
(
'<div attribute="value"\n'
' attributea="value"\n'
' attributeb="value"\n'
' attributec="value"\n'
' attributed="value"\n'
' attributef="value">\n'
" string\n"
"</div>\n"
),
({"line_break_after_multiline_tag": True}),
id="line_break_after_multiline_tag_when_already_condensed",
),
]


@pytest.mark.parametrize(("source", "expected", "args"), test_data)
def test_base(source, expected, args):
output = formatter(config_builder(args), source)

printer(expected, source, output)
assert expected == output
Loading

0 comments on commit c3ef7c0

Please sign in to comment.