mirror of
https://github.com/Hopiu/djLint.git
synced 2026-05-01 02:14:51 +00:00
updated reformat rules
This commit is contained in:
parent
46d7899978
commit
416c63ff38
5 changed files with 129 additions and 56 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# djlint
|
||||
|
||||
Simple Django template linter and reformatter.
|
||||
Simple Django template linter and reformatter. Ps, reformatting might work with Jinja and Handlebar templates as well! Test it out with the `--check` flag.
|
||||
|
||||
[](https://codecov.io/gh/Riverside-Healthcare/djlint)
|
||||
[](https://github.com/Riverside-Healthcare/djlint/actions/workflows/test.yml)
|
||||
|
|
@ -75,3 +75,7 @@ A good rule consists of
|
|||
- Code - Codes beginning with "E" signify error, and "W" warning.
|
||||
- Message - Message to display when error is found.
|
||||
- Patterns - regex expressions that will find the error.
|
||||
|
||||
## Contributing - Please Help!
|
||||
|
||||
Checkout the issue list and help where you can!
|
||||
|
|
|
|||
|
|
@ -69,6 +69,24 @@ def format_attributes(match):
|
|||
)
|
||||
|
||||
|
||||
def add_newlines(match):
|
||||
"""Only add newlines of the match is not in our acceptable one line pattern."""
|
||||
|
||||
g_one = match.group(1)
|
||||
g_two = match.group(2)
|
||||
|
||||
# print("one")
|
||||
# print(g_one)
|
||||
# print("two")
|
||||
# print(g_two)
|
||||
|
||||
if not re.search(tag_pos_inline, g_one + g_two, flags=re.IGNORECASE | re.MULTILINE):
|
||||
# print("not matched")
|
||||
return g_one + "\n" + g_two
|
||||
else:
|
||||
return g_one + g_two
|
||||
|
||||
|
||||
def remove_indentation(rawcode):
|
||||
"""Remove indentation from raw code."""
|
||||
rawcode_flat = ""
|
||||
|
|
@ -79,11 +97,11 @@ def remove_indentation(rawcode):
|
|||
|
||||
# ignore raw code
|
||||
if re.search(tag_raw_flat_closing, item, re.IGNORECASE):
|
||||
tmp = clean_line(item)
|
||||
# tmp = item #clean_line(item)
|
||||
is_block_raw = False
|
||||
|
||||
elif re.search(tag_raw_flat_opening, item, re.IGNORECASE):
|
||||
tmp = clean_line(item)
|
||||
# tmp = item #clean_line(item)
|
||||
is_block_raw = True
|
||||
|
||||
# find ignored blocks and retain indentation, otherwise strip white space
|
||||
|
|
@ -92,7 +110,7 @@ def remove_indentation(rawcode):
|
|||
is_block_ignored = False
|
||||
|
||||
elif re.search(ignored_tag_opening, item, re.IGNORECASE):
|
||||
tmp = item
|
||||
tmp = clean_line(item)
|
||||
is_block_ignored = True
|
||||
|
||||
# not filtered so just output it
|
||||
|
|
@ -104,7 +122,24 @@ def remove_indentation(rawcode):
|
|||
tmp = item
|
||||
|
||||
else:
|
||||
tmp = item.strip()
|
||||
tmp = clean_line(item) # item.strip()
|
||||
|
||||
# if not an acceptable inline tag then add breaks
|
||||
|
||||
# add missing line breaks before tag
|
||||
# print("before")
|
||||
tmp = re.sub(
|
||||
tag_newline_before,
|
||||
add_newlines,
|
||||
tmp,
|
||||
flags=re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
# print("after")
|
||||
# add missing line breaks after tag
|
||||
tmp = re.sub(
|
||||
tag_newline_after, add_newlines, tmp, flags=re.IGNORECASE | re.MULTILINE
|
||||
)
|
||||
# print(tmp)
|
||||
|
||||
rawcode_flat = rawcode_flat + tmp + "\n"
|
||||
|
||||
|
|
@ -116,17 +151,12 @@ def remove_indentation(rawcode):
|
|||
flags=re.IGNORECASE | re.DOTALL | re.MULTILINE,
|
||||
)
|
||||
|
||||
# add missing line breaks before tag
|
||||
# put empty tags on one line
|
||||
rawcode_flat = re.sub(
|
||||
tag_newline_before,
|
||||
r"\1\n\2",
|
||||
r"(<([\w]+)[^>]*>)\n(<\/\2>)",
|
||||
r"\1\3",
|
||||
rawcode_flat,
|
||||
flags=re.IGNORECASE | re.DOTALL | re.MULTILINE,
|
||||
)
|
||||
|
||||
# add missing line breaks after tag
|
||||
rawcode_flat = re.sub(
|
||||
tag_newline_after, r"\1\n\2", rawcode_flat, flags=re.IGNORECASE | re.MULTILINE
|
||||
flags=re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
|
||||
return rawcode_flat
|
||||
|
|
@ -142,77 +172,104 @@ def add_indentation(rawcode):
|
|||
blank_counter = 0
|
||||
|
||||
for item in rawcode_flat_list:
|
||||
# print(is_block_raw)
|
||||
# print(item)
|
||||
|
||||
# if a raw tag then start ignoring
|
||||
if (
|
||||
tag_raw_flat_closing
|
||||
and re.search(tag_raw_flat_closing, item, re.IGNORECASE)
|
||||
) or re.search(ignored_tag_closing, item, re.IGNORECASE):
|
||||
# print("tag raw flat closing")
|
||||
is_block_raw = False
|
||||
|
||||
# if a one-line, inline tag, just process it
|
||||
if re.search(tag_pos_inline, item, re.IGNORECASE):
|
||||
if re.search(tag_pos_inline, item, re.IGNORECASE) and is_block_raw == False:
|
||||
# print("tag pos inline")
|
||||
tmp = (indent * indent_level) + item
|
||||
blank_counter = 0
|
||||
|
||||
# if unindent, move left
|
||||
elif re.search(tag_unindent, item, re.IGNORECASE):
|
||||
elif re.search(tag_unindent, item, re.IGNORECASE) and is_block_raw == False:
|
||||
# print("tag unindent")
|
||||
indent_level = indent_level - 1
|
||||
tmp = (indent * indent_level) + item
|
||||
blank_counter = 0
|
||||
|
||||
elif re.search(tag_unindent_line, item, re.IGNORECASE):
|
||||
elif (
|
||||
re.search(tag_unindent_line, item, re.IGNORECASE) and is_block_raw == False
|
||||
):
|
||||
# print("tag unindent line")
|
||||
tmp = (indent * (indent_level - 1)) + item
|
||||
blank_counter = 0
|
||||
|
||||
# if indent, move right
|
||||
elif re.search(tag_indent, item, re.IGNORECASE):
|
||||
elif re.search(tag_indent, item, re.IGNORECASE) and is_block_raw == False:
|
||||
# print("tag indent")
|
||||
tmp = (indent * indent_level) + item
|
||||
indent_level = indent_level + 1
|
||||
blank_counter = 0
|
||||
|
||||
# if raw, flatten! no indenting!
|
||||
elif tag_raw_flat_opening and re.search(
|
||||
tag_raw_flat_opening, item, re.IGNORECASE
|
||||
):
|
||||
tmp = item
|
||||
is_block_raw = True
|
||||
blank_counter = 0
|
||||
|
||||
elif tag_raw_flat_closing and re.search(
|
||||
tag_raw_flat_closing, item, re.IGNORECASE
|
||||
):
|
||||
tmp = item
|
||||
is_block_raw = False
|
||||
blank_counter = 0
|
||||
|
||||
elif is_block_raw is True:
|
||||
# print("is raw")
|
||||
tmp = item
|
||||
|
||||
# if just a blank line
|
||||
elif item.strip() == "":
|
||||
# print("is blank")
|
||||
if blank_counter < int(reduce_extralines_gt) or blank_counter + 1:
|
||||
tmp = item.strip()
|
||||
|
||||
# otherwise, just leave same level
|
||||
else:
|
||||
tmp = item # (indent * indent_level) + item
|
||||
# print("else")
|
||||
tmp = (indent * indent_level) + item
|
||||
|
||||
# if not raw, we can try to fix django tags
|
||||
tmp = re.sub(r"({[{|%])(\w[^}].+?)([}|%]})", r"\1 \2\3", tmp)
|
||||
tmp = re.sub(r"({[{|%])([^}].+?[^ ])([}|%]})", r"\1\2 \3", tmp)
|
||||
|
||||
# handlebars templates
|
||||
tmp = re.sub(r"({{#(?:each|if).+?[^ ])(}})", r"\1 \2", tmp)
|
||||
|
||||
# if a opening raw tag then start ignoring.. only if there is no closing tag
|
||||
# on the same line
|
||||
if (
|
||||
tag_raw_flat_closing
|
||||
and re.search(tag_raw_flat_opening, item, re.IGNORECASE)
|
||||
) or re.search(ignored_tag_opening, item, re.IGNORECASE):
|
||||
# print("tag raw flat opening")
|
||||
is_block_raw = True
|
||||
|
||||
# if a normal tag, we can try to expand attributes
|
||||
elif (
|
||||
format_long_attributes
|
||||
and is_block_raw == False
|
||||
and len(tmp) > max_line_length
|
||||
):
|
||||
# get leading space, and attributes
|
||||
tmp = re.sub(r"(\s*?)(<\w+)(.+?)(/?>)", format_attributes, tmp)
|
||||
|
||||
# turn off raw block if we hit end - for one line raw blocks
|
||||
if (
|
||||
tag_raw_flat_closing
|
||||
and re.search(tag_raw_flat_closing, item, re.IGNORECASE)
|
||||
) or re.search(ignored_tag_closing, item, re.IGNORECASE):
|
||||
is_block_raw = False
|
||||
|
||||
# print(tmp)
|
||||
|
||||
beautified_code = beautified_code + tmp + "\n"
|
||||
|
||||
if format_long_attributes:
|
||||
# find lines longer than x
|
||||
new_beautified = ""
|
||||
for line in beautified_code.splitlines():
|
||||
if len(line) > max_line_length:
|
||||
# get leading space, and attributes
|
||||
line = re.sub(r"(\s*?)(<\w+)(.+?)(/?>)", format_attributes, line)
|
||||
|
||||
new_beautified += "\n" + line
|
||||
beautified_code = new_beautified
|
||||
|
||||
return beautified_code.strip() + "\n"
|
||||
|
||||
|
||||
def reformat_file(check: bool, this_file: Path):
|
||||
"""Reformat html file."""
|
||||
rawcode = this_file.read_text(encoding="utf8")
|
||||
|
||||
# print(remove_indentation(rawcode))
|
||||
beautified_code = add_indentation(remove_indentation(rawcode))
|
||||
|
||||
# print(beautified_code)
|
||||
if check is not True:
|
||||
# update the file
|
||||
this_file.write_text(beautified_code)
|
||||
|
|
|
|||
|
|
@ -83,3 +83,8 @@
|
|||
message: Missging title tag in html.
|
||||
patterns:
|
||||
- <html[^>]*?>(?:(?!<title>).)*</html>
|
||||
- rule:
|
||||
name: W017
|
||||
message: Tag should be self closing.
|
||||
patterns:
|
||||
- <(img|input|area|base|br|col|embed|hr|link|meta|param|source|track|wbr|command|keygen|menuitem)[^/]*?>
|
||||
|
|
|
|||
|
|
@ -6,28 +6,28 @@
|
|||
indent = " "
|
||||
|
||||
# indicates tags whose contents should not be formatted
|
||||
ignored_tag_opening = r"<script|<style|<!--|{\*|<\?php|<pre"
|
||||
ignored_tag_opening = r"<script|<style|<!--|{\*|<\?php|<pre|<svg"
|
||||
|
||||
# indicates when to stop ignoring
|
||||
ignored_tag_closing = r"</script|</style|-->|\*}|\?>|</pre"
|
||||
ignored_tag_closing = r"</script|</style|-->|\*}|\?>|</pre|</svg"
|
||||
|
||||
# the contents of these tag blocks will be start on a new line
|
||||
tag_newline_before = r"([^\n])((?:\{% +?(?:if|end|for|block|endblock|else|spaceless|compress|load|include)|(?:<script)|(?:</?(html|head|body|div|a|nav|ul|ol|dl|li|table|thead|tbody|tr|th|td|blockquote|select|form|option|optgroup|fieldset|legend|label|header|main|section|aside|footer|figure|video|span|p|g|svg|button|h\d))))"
|
||||
tag_newline_before = r"([^\n]+?)((?:(?:\{\{[\/|\#])|\{% +?(?:if|end|for|block|endblock|else|spaceless|compress|load|include)|(?:<script)|(?:{% endverbatim %})|(?:{% verbatim %})|(?:</?(html|head|body|div|cache|a|nav|ul|ol|dl|li|table|thead|tbody|tr|th|td|blockquote|select|form|option|optgroup|fieldset|legend|label|header|main|section|aside|footer|figure|video|span|p|g|svg|button|img|source)[^>]*?>.*?)))"
|
||||
|
||||
# these tags should be followed by a newline
|
||||
tag_newline_after = r"((?:\{% +?(?:if|end|for|block|else|spaceless|compress|load|include)(?:.*?%}))|(?:<html|<head|</head|<body|</body|</script|<div|</div|<nav|</nav|<ul|</ul|<ol|</ol|<dl|</dl|<li|</li|<table|</table|<thead|</thead|<tbody|</tbody|<tr|</tr|<th|</th|<td|</td|<blockquote|</blockquote|<select|</select|<form|</form|<option|</option|<optgroup|</optgroup|<fieldset|</fieldset|<legend|</legend|<label|</label|<header|</header|<main|</main|<section|</section|<aside|</aside|<footer|</footer|<figure|</figure|<video|</video|</span|<p|</p|<g|</g|<svg|</svg|</h\d).*?\>)([^\n])"
|
||||
tag_newline_after = r"((?:(?:\{\{[\/\#].*?\}\})|\{% +?(?:if|end|for|block|else|spaceless|compress|load|include)(?:.*?%}))|(?:{% endverbatim %})|(?:{% verbatim %})|(?:<html|<head|</head|<body|</body|</script|<div|</div|<cache|</cache|<nav|</nav|<ul|</ul|<ol|</ol|<dl|</dl|<li|</li|<table|</table|<thead|</thead|<tbody|</tbody|<tr|</tr|<th|</th|<td|</td|<blockquote|</blockquote|<select|</select|<form|</form|<option|</option|<optgroup|</optgroup|<fieldset|</fieldset|<legend|</legend|<label|</label|<header|</header|<main|</main|<section|</section|<aside|</aside|<footer|</footer|<figure|</figure|<video|</video|<source|</source|</span|<p|</p|<g|</g|<svg|</svg|</h\d|<img).*?\>)([^\n]+)"
|
||||
|
||||
# the contents of these tag blocks will be indented
|
||||
tag_indent = r"\{% +?(if|for|block|else|spaceless|compress)|(?:<(?:html|head|body|div|a|nav|ul|ol|dl|li|table|thead|tbody|tr|th|td|blockquote|select|form|option|optgroup|fieldset|legend|label|header|main|section|aside|footer|figure|video|span|p|g|svg|h\d|button))"
|
||||
tag_indent = r"(?:\{\{\#)|\{% +?(if|for|block|else|spaceless|compress)|(?:{% verbatim %})|(?:<(?:html|head|body|div|a|nav|ul|ol|dl|li|table|thead|tbody|tr|th|td|blockquote|select|form|option|cache|optgroup|fieldset|legend|label|header|main|section|aside|footer|figure|video|span|p|g|svg|h\d|button|img|script|style|source))"
|
||||
|
||||
# this signals when tags should be unindented (see tags above)
|
||||
tag_unindent = r"\{% end|(?:</(?:html|head|body|div|a|nav|ul|ol|dl|li|table|thead|tbody|tr|th|td|blockquote|select|form|option|optgroup|fieldset|legend|label|header|main|section|aside|footer|figure|video|span|p|g|svg|h\d|button))"
|
||||
tag_unindent = r"(?:\{\{\/)|\{% end|(?:{% endverbatim %})|(?:</(?:html|head|body|div|a|nav|ul|ol|dl|li|table|thead|tbody|tr|th|td|blockquote|select|form|option|optgroup|fieldset|legend|label|header|cache|main|section|aside|footer|figure|video|span|p|g|svg|h\d|button|img|script|style|source))"
|
||||
|
||||
# these tags should be unindented and next line will be indented
|
||||
tag_unindent_line = r"\{% el"
|
||||
tag_unindent_line = r"(?:\{% el)|(?:\{\{ *?(?:else|\^) *?\}\})"
|
||||
|
||||
# these tags can sometimes be on one line
|
||||
tag_pos_inline = r"\{% if.*endif %\}|\{% block.*endblock %\}|<link.*/>|<link.*\">|<link.*>|<meta.*/>|<script.*</script>|<div.*</div>|<a.*</a>|<li.*</li>|<dt.*</dt>|<dd.*</dd>|<th.*</th>|<td.*</td>|<legend.*</legend>|<label.*</label>|<option.*</option>|<input.*/>|<input.*\">|<span.*</span>|<p.*</p>|<path.*/>|<!--.*-->|<button.*</button>|<h\d.*</h\d>"
|
||||
tag_pos_inline = r"(?:<link.*/>|<link.*\">|<link.*>|<meta.*/>|<script.*</script>|<div[^>]*>[^<]*</div>|<a[^>]*>[^<]*</a>|<li[^>]*>[^<]*</li>|<dt[^>]*>[^<]*</dt>|<dd[^>]*>[^<]*</dd>|<th[^>]*>[^<]*</th>|<td[^>]*>[^<]*</td>|<legend[^>]*>[^<]*</legend>|<label[^>]*>[^<]*</label>|<option[^>]*>[^<]*</option>|<input.*/>|<input.*\">|<span[^>]*>[^<]*</span>|<p[^>]*>[^<]*</p>|<path.*/>|<!--.*-->|<button[^>]*>[^<]*</button>|<h\d[^>]*>[^<]*</h\d>|<img.*?/>)"
|
||||
|
||||
# these tags use raw code and should flatten to column 1
|
||||
# tabs will be removed inside these tags! use spaces for spacing if needed!
|
||||
|
|
@ -45,7 +45,7 @@ max_line_length = 99
|
|||
format_long_attributes = True
|
||||
|
||||
# pattern used to find attributes in a tag
|
||||
attribute_pattern = r"([a-zA-Z-_]+=(?:\".*?\"|\'.*?\')|required|checked)\s*"
|
||||
attribute_pattern = r"(.+?=(?:\".*?\"|\'.*?\')|required|checked)\s*"
|
||||
tag_pattern = r"(<\w+?)((?:\n\s*?[^>]+?)+?)(/?\>)"
|
||||
|
||||
ignored_paths = r"(?:\.tox|\.venv|node_modules|_build)"
|
||||
|
|
|
|||
|
|
@ -191,3 +191,10 @@ def test_W016(runner, tmp_file):
|
|||
result = runner.invoke(djlint, [tmp_file.name])
|
||||
assert result.exit_code == 0
|
||||
assert "W016 1:" in result.output
|
||||
|
||||
|
||||
def test_W017(runner, tmp_file):
|
||||
write_to_file(tmp_file.name, b"<img this >")
|
||||
result = runner.invoke(djlint, [tmp_file.name])
|
||||
assert result.exit_code == 0
|
||||
assert "W017 1:" in result.output
|
||||
|
|
|
|||
Loading…
Reference in a new issue