mirror of
https://github.com/Hopiu/djLint.git
synced 2026-05-21 11:21:51 +00:00
changed build system to poetry, added more dj tags, added pyproject.toml support, fixed #11, closed #12, closed #1
This commit is contained in:
parent
37d8d48cb6
commit
94c1dd5958
8 changed files with 694 additions and 374 deletions
|
|
@ -21,6 +21,7 @@ import sys
|
|||
from concurrent.futures import ProcessPoolExecutor, as_completed
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
import click
|
||||
from click import echo
|
||||
|
|
@ -29,22 +30,21 @@ from tqdm import tqdm
|
|||
|
||||
from .lint import lint_file
|
||||
from .reformat import reformat_file
|
||||
from .settings import ignored_paths
|
||||
from .settings import Config
|
||||
|
||||
|
||||
def get_src(src: Path, extension=None):
|
||||
def get_src(src: Path, config: Config) -> List[Path]:
|
||||
"""Get source files."""
|
||||
if Path.is_file(src):
|
||||
return [src]
|
||||
|
||||
# remove leading . from extension
|
||||
extension = str(config.extension)
|
||||
extension = extension[1:] if extension.startswith(".") else extension
|
||||
|
||||
paths = list(
|
||||
filter(
|
||||
lambda x: not re.search(
|
||||
"|".join([re.escape(x) for x in ignored_paths]), str(x)
|
||||
),
|
||||
lambda x: not re.search(config.ignored_paths, str(x), re.VERBOSE),
|
||||
list(src.glob(r"**/*.%s" % extension)),
|
||||
)
|
||||
)
|
||||
|
|
@ -56,7 +56,7 @@ def get_src(src: Path, extension=None):
|
|||
return paths
|
||||
|
||||
|
||||
def build_output(error):
|
||||
def build_output(error: dict) -> int:
|
||||
"""Build output for file errors."""
|
||||
errors = sorted(list(error.values())[0], key=lambda x: int(x["line"].split(":")[0]))
|
||||
width, _ = shutil.get_terminal_size()
|
||||
|
|
@ -75,10 +75,9 @@ def build_output(error):
|
|||
)
|
||||
|
||||
for message in errors:
|
||||
error = bool(message["code"][:1] == "E")
|
||||
echo(
|
||||
"{} {} {} {} {}".format(
|
||||
(Fore.RED if error else Fore.YELLOW),
|
||||
(Fore.RED if bool(message["code"][:1] == "E") else Fore.YELLOW),
|
||||
message["code"] + Style.RESET_ALL,
|
||||
Fore.BLUE + message["line"] + Style.RESET_ALL,
|
||||
message["message"],
|
||||
|
|
@ -89,7 +88,7 @@ def build_output(error):
|
|||
return len(errors)
|
||||
|
||||
|
||||
def build_check_output(errors, quiet):
|
||||
def build_check_output(errors: dict, quiet: bool) -> int:
|
||||
"""Build output for reformat check."""
|
||||
if len(errors) == 0:
|
||||
return 0
|
||||
|
|
@ -128,12 +127,12 @@ def build_check_output(errors, quiet):
|
|||
return len(list(filter(lambda x: len(x) > 0, errors.values())))
|
||||
|
||||
|
||||
def build_quantity(size: int):
|
||||
def build_quantity(size: int) -> str:
|
||||
"""Count files in a list."""
|
||||
return "%d file%s" % (size, ("s" if size > 1 or size == 0 else ""))
|
||||
|
||||
|
||||
def build_quantity_tense(size: int):
|
||||
def build_quantity_tense(size: int) -> str:
|
||||
"""Count files in a list."""
|
||||
return "%d file%s %s" % (
|
||||
size,
|
||||
|
|
@ -155,7 +154,7 @@ def build_quantity_tense(size: int):
|
|||
"-e",
|
||||
"--extension",
|
||||
type=str,
|
||||
default="html",
|
||||
default="",
|
||||
help="File extension to lint",
|
||||
show_default=True,
|
||||
)
|
||||
|
|
@ -184,9 +183,11 @@ def build_quantity_tense(size: int):
|
|||
)
|
||||
def main(
|
||||
src: str, extension: str, ignore: str, reformat: bool, check: bool, quiet: bool
|
||||
):
|
||||
) -> None:
|
||||
"""Djlint django template files."""
|
||||
file_list = get_src(Path(src), extension)
|
||||
config = Config(src, extension=extension, ignore=ignore, quiet=quiet)
|
||||
|
||||
file_list = get_src(Path(src), config)
|
||||
|
||||
if len(file_list) == 0:
|
||||
return
|
||||
|
|
@ -225,13 +226,13 @@ def main(
|
|||
with ProcessPoolExecutor(max_workers=worker_count) as exe:
|
||||
file_errors = []
|
||||
if reformat is True or check is True:
|
||||
func = partial(reformat_file, check)
|
||||
func = partial(reformat_file, config, check)
|
||||
futures = {
|
||||
exe.submit(func, this_file): this_file for this_file in file_list
|
||||
}
|
||||
|
||||
else:
|
||||
func = partial(lint_file, ignore)
|
||||
func = partial(lint_file, config)
|
||||
futures = {
|
||||
exe.submit(func, this_file): this_file for this_file in file_list
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,11 @@
|
|||
"""djLint Attempt to logically shrink html."""
|
||||
import re as old_re
|
||||
|
||||
import regex as re
|
||||
|
||||
from ..settings import (
|
||||
ignored_block_closing,
|
||||
ignored_block_opening,
|
||||
ignored_group_closing,
|
||||
ignored_group_opening,
|
||||
ignored_inline_blocks,
|
||||
single_line_html_tags,
|
||||
single_line_template_tags,
|
||||
start_template_tags,
|
||||
)
|
||||
from ..settings import Config
|
||||
|
||||
|
||||
def _clean_line(line):
|
||||
def _clean_line(line: str) -> str:
|
||||
"""Clean up a line of html.
|
||||
|
||||
* remove duplicate spaces
|
||||
|
|
@ -25,7 +15,7 @@ def _clean_line(line):
|
|||
return re.sub(r" {2,}", " ", line.strip())
|
||||
|
||||
|
||||
def _strip_html_whitespace(html):
|
||||
def _strip_html_whitespace(html: str, config: Config) -> str:
|
||||
"""Remove unnecessary whitespace from text."""
|
||||
rawcode_flat = ""
|
||||
is_block_ignored = False
|
||||
|
|
@ -35,17 +25,19 @@ def _strip_html_whitespace(html):
|
|||
|
||||
# start of ignored block. If we are already in an ingored block, keep true.
|
||||
is_group_ignored = is_group_ignored or bool(
|
||||
re.search("|".join(ignored_group_opening), item, re.IGNORECASE)
|
||||
re.search(config.ignored_group_opening, item, re.IGNORECASE | re.VERBOSE)
|
||||
)
|
||||
|
||||
# find ignored blocks and retain indentation, otherwise strip white space
|
||||
if re.findall(
|
||||
r"(?:%s)" % "|".join(ignored_inline_blocks), item, flags=re.IGNORECASE
|
||||
r"(?:%s)" % config.ignored_inline_blocks,
|
||||
item,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
):
|
||||
tmp = _clean_line(item)
|
||||
|
||||
elif (
|
||||
re.search("|".join(ignored_block_closing), item, re.IGNORECASE)
|
||||
re.search(config.ignored_block_closing, item, re.IGNORECASE | re.VERBOSE)
|
||||
and is_group_ignored is False
|
||||
):
|
||||
# do not format ignored lines
|
||||
|
|
@ -53,7 +45,7 @@ def _strip_html_whitespace(html):
|
|||
is_block_ignored = False
|
||||
|
||||
elif (
|
||||
re.search("|".join(ignored_block_opening), item, re.IGNORECASE)
|
||||
re.search(config.ignored_block_opening, item, re.IGNORECASE | re.VERBOSE)
|
||||
and is_group_ignored is False
|
||||
):
|
||||
# do not format ignored lines
|
||||
|
|
@ -67,7 +59,9 @@ def _strip_html_whitespace(html):
|
|||
tmp = _clean_line(item)
|
||||
|
||||
# end of ignore raw code
|
||||
if bool(re.search("|".join(ignored_group_closing), item, re.IGNORECASE)):
|
||||
if bool(
|
||||
re.search(config.ignored_group_closing, item, re.IGNORECASE | re.VERBOSE)
|
||||
):
|
||||
is_group_ignored = False
|
||||
|
||||
rawcode_flat = rawcode_flat + tmp + "\n"
|
||||
|
|
@ -75,10 +69,10 @@ def _strip_html_whitespace(html):
|
|||
return rawcode_flat
|
||||
|
||||
|
||||
def compress_html(html):
|
||||
def compress_html(html: str, config: Config) -> str:
|
||||
"""Compress back tags that do not need to be expanded."""
|
||||
# put empty tags on one line
|
||||
html = _strip_html_whitespace(html)
|
||||
html = _strip_html_whitespace(html, config)
|
||||
|
||||
html = re.sub(
|
||||
r"(<([\w]+)[^>]*>)\s+?(<\/\2>)",
|
||||
|
|
@ -89,22 +83,26 @@ def compress_html(html):
|
|||
|
||||
# put empty template tags on one line
|
||||
html = re.sub(
|
||||
r"(" + start_template_tags + r")\s+?(\{\% end[^}]*?\%\})",
|
||||
r"\1\2",
|
||||
r"({%[ ]*?("
|
||||
+ re.sub(r"\s", "", config.start_template_tags)
|
||||
+ r")[^}]+?%})\s+?(\{\% end[^}]*?\%\})",
|
||||
r"\1\3",
|
||||
html,
|
||||
re.MULTILINE,
|
||||
)
|
||||
|
||||
# put short single line tags on one line
|
||||
slt_html = "|".join(single_line_html_tags)
|
||||
html = old_re.sub(
|
||||
# verbose doesn't seem to work with replace groups.
|
||||
slt_html = re.sub(r"\s", "", config.single_line_html_tags)
|
||||
|
||||
html = re.sub(
|
||||
r"(<(%s)>)\s*([^<\n]{,80})\s*?(</(\2)>)" % slt_html,
|
||||
r"\1\3\4",
|
||||
html,
|
||||
re.IGNORECASE | re.MULTILINE | re.DOTALL,
|
||||
)
|
||||
|
||||
html = old_re.sub(
|
||||
html = re.sub(
|
||||
r"(<(%s)>)\s*?([^<\n]{,80})\s*?(</(\2)>)" % slt_html,
|
||||
r"\1\3\4",
|
||||
html,
|
||||
|
|
@ -112,17 +110,17 @@ def compress_html(html):
|
|||
)
|
||||
|
||||
html = re.sub(
|
||||
r"(<(%s) [^\n]{,80}>)\s*([^<\n]{,80})\s*?(</(\2)>)" % slt_html,
|
||||
r"(<(%s)[ ][^\n]{,80}>)\s*([^<\n]{,80})\s*?(</(\2)>)" % slt_html,
|
||||
r"\1\3\4",
|
||||
html,
|
||||
re.IGNORECASE | re.MULTILINE | re.DOTALL,
|
||||
)
|
||||
|
||||
slt_template = "|".join(single_line_template_tags)
|
||||
# cannot use verbose when replacing with var. 🤕
|
||||
html = re.sub(
|
||||
r"({% +?("
|
||||
+ slt_template
|
||||
+ r") +?[^\n]{,30}%})\s*([^%\n]{,50})\s*?({% +?end(\2) +?%})",
|
||||
r"({%[ ]*?("
|
||||
+ re.sub(r"\s", "", config.single_line_template_tags)
|
||||
+ r")[ ]+?[^\n]{,30}%})\s*([^%\n]{,50})\s*?({%[ ]+?end(\2)[ ]*?%})",
|
||||
r"\1\3\4",
|
||||
html,
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
|
|
|
|||
|
|
@ -4,73 +4,70 @@ from functools import partial
|
|||
|
||||
import regex as re
|
||||
|
||||
from ..settings import (
|
||||
break_html_tags,
|
||||
break_template_tags,
|
||||
ignored_attributes,
|
||||
ignored_blocks,
|
||||
tag_pattern,
|
||||
)
|
||||
from ..settings import Config
|
||||
|
||||
|
||||
def _flatten_attributes(match):
|
||||
def _flatten_attributes(config: Config, match: re.Match) -> str:
|
||||
"""Flatten multiline attributes back to one line.
|
||||
|
||||
Skip when attribute is ignored.
|
||||
Attribute name can be in group one or group 2.
|
||||
for now, skipping if they are anywhere
|
||||
"""
|
||||
for attribute in ignored_attributes:
|
||||
for attribute in config.ignored_attributes:
|
||||
if attribute in match.group():
|
||||
return match.group()
|
||||
|
||||
return "{} {}{}".format(
|
||||
match.group(1),
|
||||
" ".join(match.group(2).strip().splitlines()),
|
||||
" ".join(x.strip() for x in match.group(2).strip().splitlines()),
|
||||
match.group(3),
|
||||
)
|
||||
|
||||
|
||||
def _should_ignore(html, match):
|
||||
def _should_ignore(config: Config, html: str, match: re.Match) -> bool:
|
||||
"""Do not add whitespace if the tag is in a non indent block."""
|
||||
for block in ignored_blocks:
|
||||
for block in config.ignored_blocks:
|
||||
return any(
|
||||
ignored_match.start() < match.start(1)
|
||||
and ignored_match.end() > match.end(1)
|
||||
for ignored_match in re.finditer(
|
||||
block % re.escape(match.group(1)), html, re.DOTALL | re.IGNORECASE
|
||||
block % re.escape(match.group(1)),
|
||||
html,
|
||||
re.DOTALL | re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def expand_html(html):
|
||||
def expand_html(html: str, config: Config) -> str:
|
||||
"""Split single line html into many lines based on tags."""
|
||||
|
||||
def add_html_line(out_format, match):
|
||||
def add_html_line(out_format: str, match: re.Match) -> str:
|
||||
"""Add whitespace.
|
||||
|
||||
Do not add whitespace if the tag is in a non indent block.
|
||||
"""
|
||||
if _should_ignore(html, match):
|
||||
if _should_ignore(config, html, match):
|
||||
return match.group(1)
|
||||
|
||||
return out_format % match.group(1)
|
||||
|
||||
# put attributes on one line
|
||||
func = partial(_flatten_attributes, config)
|
||||
html = old_re.sub(
|
||||
tag_pattern,
|
||||
_flatten_attributes,
|
||||
config.tag_pattern,
|
||||
func,
|
||||
html,
|
||||
flags=re.IGNORECASE | re.MULTILINE,
|
||||
flags=re.IGNORECASE | re.MULTILINE | re.VERBOSE,
|
||||
)
|
||||
|
||||
html_tags = "|".join(break_html_tags)
|
||||
html_tags = config.break_html_tags
|
||||
|
||||
# process opening tags ############
|
||||
|
||||
# the tag either closes <div>
|
||||
# the tag either opens <div>
|
||||
# self closes <img />
|
||||
# has attributes <div text>
|
||||
# or has attributes and self closes <img text/>
|
||||
|
|
@ -78,7 +75,7 @@ def expand_html(html):
|
|||
add_left = partial(add_html_line, "\n%s")
|
||||
add_right = partial(add_html_line, "%s\n")
|
||||
|
||||
break_char = r"(?<!\n *?)"
|
||||
break_char = r"(?<!\n[ ]*?)"
|
||||
|
||||
html = re.sub(
|
||||
r"%s\K(<(?:%s)>)"
|
||||
|
|
@ -88,62 +85,71 @@ def expand_html(html):
|
|||
),
|
||||
add_left,
|
||||
html,
|
||||
flags=re.IGNORECASE,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
# <tag>
|
||||
html = re.sub(
|
||||
r"(<(?:%s)>)(?=[^\n])" % html_tags, add_right, html, flags=re.IGNORECASE
|
||||
r"(<(?:%s)>)(?=[^\n])" % html_tags,
|
||||
add_right,
|
||||
html,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
# \n<tag /> and \n<tag/>
|
||||
html = re.sub(
|
||||
r"%s\K(<(?:%s) ?/>)"
|
||||
r"%s\K(<(?:%s)[ ]?/>)"
|
||||
% (
|
||||
break_char,
|
||||
html_tags,
|
||||
),
|
||||
add_left,
|
||||
html,
|
||||
flags=re.IGNORECASE,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
# <tag /> and <tag/>
|
||||
html = re.sub(
|
||||
r"(<(?:%s) ?/>)(?=[^\n])" % html_tags, add_right, html, flags=re.IGNORECASE
|
||||
r"(<(?:%s)[ ]?/>)(?=[^\n])" % html_tags,
|
||||
add_right,
|
||||
html,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
# \n<tag stuff/>, \n<tag stuff>, \n<tag stuff />
|
||||
html = re.sub(
|
||||
r"%s\K(<(?:%s) [^>]*?[^/]>)"
|
||||
r"%s\K(<(?:%s)[ ][^>]*?[^/]>)"
|
||||
% (
|
||||
break_char,
|
||||
html_tags,
|
||||
),
|
||||
add_left,
|
||||
html,
|
||||
flags=re.IGNORECASE,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
# <tag stuff/>, <tag stuff>, <tag stuff />
|
||||
html = re.sub(
|
||||
r"(<(?:%s) [^>]*?[^/]>)(?=[^\n])" % html_tags,
|
||||
r"(<(?:%s)[ ][^>]*?[^/]>)(?=[^\n])" % html_tags,
|
||||
add_right,
|
||||
html,
|
||||
flags=re.IGNORECASE,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
html = re.sub(
|
||||
r"%s\K(<(?:%s) [^>]+?/>)"
|
||||
r"%s\K(<(?:%s)[ ][^>]+?/>)"
|
||||
% (
|
||||
break_char,
|
||||
html_tags,
|
||||
),
|
||||
add_left,
|
||||
html,
|
||||
flags=re.IGNORECASE,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
html = re.sub(
|
||||
r"(<(?:%s) [^>]+?/>)(?=[^\n])" % html_tags, add_right, html, flags=re.IGNORECASE
|
||||
r"(<(?:%s)[ ][^>]+?/>)(?=[^\n])" % html_tags,
|
||||
add_right,
|
||||
html,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
# process closing (break_char, html_tags,)s ######
|
||||
|
|
@ -156,50 +162,57 @@ def expand_html(html):
|
|||
),
|
||||
add_left,
|
||||
html,
|
||||
flags=re.IGNORECASE,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
html = re.sub(
|
||||
r"(</(?:%s)>)(?=[^\n])" % html_tags, add_right, html, flags=re.IGNORECASE
|
||||
r"(</(?:%s)>)(?=[^\n])" % html_tags,
|
||||
add_right,
|
||||
html,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
|
||||
# template tag breaks
|
||||
|
||||
def should_i_move_template_tag(out_format, match):
|
||||
def should_i_move_template_tag(out_format: str, match: re.Match) -> str:
|
||||
# ensure template tag is not inside an html tag
|
||||
html_tags = "|".join(break_html_tags)
|
||||
|
||||
if _should_ignore(html, match):
|
||||
if _should_ignore(config, html, match):
|
||||
return match.group(1)
|
||||
|
||||
if not re.findall(
|
||||
r"\<(?:" + html_tags + r") [^>]*?" + re.escape(match.group(1)) + "$",
|
||||
r"\<(?:"
|
||||
+ str(config.break_html_tags)
|
||||
+ r")[ ][^>]*?"
|
||||
+ re.escape(match.group(1))
|
||||
+ "$",
|
||||
html[: match.end()],
|
||||
re.MULTILINE,
|
||||
re.MULTILINE | re.VERBOSE,
|
||||
):
|
||||
|
||||
return out_format % match.group(1)
|
||||
|
||||
return match.group(1)
|
||||
|
||||
for tag in break_template_tags:
|
||||
# find all matching tags
|
||||
# template tags
|
||||
# break before
|
||||
html = re.sub(
|
||||
break_char
|
||||
+ r"\K((?:{%|{{\#)[ ]*?(?:"
|
||||
+ re.sub(r"\s", "", config.break_template_tags)
|
||||
+ ")[^}]+?[%|}]})",
|
||||
partial(should_i_move_template_tag, "\n%s"),
|
||||
html,
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
|
||||
html = re.sub(
|
||||
r"%s\K(%s)"
|
||||
% (
|
||||
break_char,
|
||||
tag,
|
||||
),
|
||||
partial(should_i_move_template_tag, "\n%s"),
|
||||
html,
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
|
||||
html = re.sub(
|
||||
r"(%s)(?=[^\n])" % tag,
|
||||
partial(should_i_move_template_tag, "%s\n"),
|
||||
html,
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
# break after
|
||||
html = re.sub(
|
||||
r"((?:{%|{{\#)[ ]*?(?:"
|
||||
+ re.sub(r"\s", "", config.break_template_tags)
|
||||
+ ")[^}]+?[%|}]})(?=[^\n])",
|
||||
partial(should_i_move_template_tag, "%s\n"),
|
||||
html,
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
|
||||
return html
|
||||
|
|
|
|||
|
|
@ -1,27 +1,13 @@
|
|||
"""djLint add indentation to html."""
|
||||
|
||||
from functools import partial
|
||||
|
||||
import regex as re
|
||||
|
||||
from ..settings import (
|
||||
always_single_line_html_tags,
|
||||
attribute_pattern,
|
||||
break_html_tags,
|
||||
format_long_attributes,
|
||||
ignored_block_closing,
|
||||
ignored_block_opening,
|
||||
ignored_group_closing,
|
||||
ignored_group_opening,
|
||||
ignored_inline_blocks,
|
||||
indent,
|
||||
max_line_length,
|
||||
single_line_template_tags,
|
||||
tag_indent,
|
||||
tag_unindent,
|
||||
tag_unindent_line,
|
||||
)
|
||||
from ..settings import Config
|
||||
|
||||
|
||||
def _format_attributes(match):
|
||||
def _format_attributes(config: Config, match: re.match) -> str:
|
||||
"""Spread long attributes over multiple lines."""
|
||||
leading_space = match.group(1)
|
||||
|
||||
|
|
@ -29,7 +15,9 @@ def _format_attributes(match):
|
|||
|
||||
spacing = "\n" + leading_space + len(tag) * " "
|
||||
|
||||
attributes = (spacing).join(re.findall(attribute_pattern, match.group(3).strip()))
|
||||
attributes = (spacing).join(
|
||||
re.findall(str(config.attribute_pattern), match.group(3).strip(), re.VERBOSE)
|
||||
)
|
||||
|
||||
close = match.group(4)
|
||||
|
||||
|
|
@ -41,70 +29,92 @@ def _format_attributes(match):
|
|||
)
|
||||
|
||||
|
||||
def indent_html(rawcode):
|
||||
def indent_html(rawcode: str, config: Config) -> str:
|
||||
"""Indent raw code."""
|
||||
rawcode_flat_list = re.split("\n", rawcode)
|
||||
|
||||
indent = config.indent
|
||||
|
||||
beautified_code = ""
|
||||
indent_level = 0
|
||||
is_block_raw = False
|
||||
|
||||
slt_html = "|".join(
|
||||
break_html_tags
|
||||
) # here using all tags cause we allow empty tags on one line
|
||||
slt_html = config.break_html_tags
|
||||
|
||||
always_slt_html = "|".join(
|
||||
always_single_line_html_tags
|
||||
) # here using all tags cause we allow empty tags on one line
|
||||
# here using all tags cause we allow empty tags on one line
|
||||
always_slt_html = config.always_single_line_html_tags
|
||||
|
||||
slt_template = "|".join(single_line_template_tags)
|
||||
# here using all tags cause we allow empty tags on one line
|
||||
slt_template = config.single_line_template_tags
|
||||
|
||||
for item in rawcode_flat_list:
|
||||
# if a raw tag then start ignoring
|
||||
if (
|
||||
re.search("|".join(ignored_group_opening), item, re.IGNORECASE)
|
||||
) or re.search("|".join(ignored_group_opening), item, re.IGNORECASE):
|
||||
if re.search(config.ignored_group_opening, item, re.IGNORECASE | re.VERBOSE):
|
||||
is_block_raw = True
|
||||
|
||||
if re.findall(
|
||||
r"(?:%s)" % "|".join(ignored_inline_blocks), item, flags=re.IGNORECASE
|
||||
config.ignored_inline_blocks, item, flags=re.IGNORECASE | re.VERBOSE
|
||||
):
|
||||
tmp = (indent * indent_level) + item + "\n"
|
||||
|
||||
# if a one-line, inline tag, just process it, only if line starts w/ it
|
||||
elif (
|
||||
re.findall(r"(<(%s)>)(.*?)(</(\2)>)" % slt_html, item, re.IGNORECASE)
|
||||
or re.findall(r"(<(%s) .+?>)(.*?)(</(\2)>)" % slt_html, item, re.IGNORECASE)
|
||||
or re.findall(
|
||||
r"^({% +?(" + slt_template + r") +?.+?%})(.*?)({% +?end(\2) +?.*?%})",
|
||||
item,
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
re.findall(
|
||||
r"(<(%s)>)(.*?)(</(\2)>)" % slt_html, item, re.IGNORECASE | re.VERBOSE
|
||||
)
|
||||
or re.findall(r"(<(%s) .*?/>)" % slt_html, item, flags=re.IGNORECASE)
|
||||
or re.findall(
|
||||
r"(<(%s) .*?/?>)" % always_slt_html, item, flags=re.IGNORECASE
|
||||
r"(<(%s)[ ].+?>)(.*?)(</(\2)>)" % slt_html,
|
||||
item,
|
||||
re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
or re.findall(
|
||||
r"^({%[ ]*?("
|
||||
+ str(slt_template)
|
||||
+ r")[ ]+?.+?%})(.*?)({%[ ]+?end(\2)[ ]+?.*?%})",
|
||||
item,
|
||||
re.IGNORECASE | re.MULTILINE | re.VERBOSE,
|
||||
)
|
||||
or re.findall(
|
||||
r"(<(%s)[ ].*?/>)" % slt_html, item, flags=re.IGNORECASE | re.VERBOSE
|
||||
)
|
||||
or re.findall(
|
||||
r"(<(%s)[ ].*?/?>)" % always_slt_html,
|
||||
item,
|
||||
flags=re.IGNORECASE | re.VERBOSE,
|
||||
)
|
||||
) and is_block_raw is False:
|
||||
tmp = (indent * indent_level) + item + "\n"
|
||||
|
||||
# if unindent, move left
|
||||
elif (
|
||||
re.search(r"^(?:" + tag_unindent + r")", item, re.IGNORECASE | re.MULTILINE)
|
||||
re.search(
|
||||
config.tag_unindent,
|
||||
item,
|
||||
re.IGNORECASE | re.MULTILINE | re.VERBOSE,
|
||||
)
|
||||
and is_block_raw is False
|
||||
or re.search("|".join(ignored_block_closing), item, re.IGNORECASE)
|
||||
or re.search(config.ignored_block_closing, item, re.IGNORECASE | re.VERBOSE)
|
||||
):
|
||||
indent_level = max(indent_level - 1, 0)
|
||||
tmp = (indent * indent_level) + item + "\n"
|
||||
|
||||
elif (
|
||||
re.search(r"^" + tag_unindent_line, item, re.IGNORECASE | re.MULTILINE)
|
||||
re.search(
|
||||
r"^" + str(config.tag_unindent_line),
|
||||
item,
|
||||
re.IGNORECASE | re.MULTILINE | re.VERBOSE,
|
||||
)
|
||||
and is_block_raw is False
|
||||
):
|
||||
tmp = (indent * (indent_level - 1)) + item + "\n"
|
||||
|
||||
# if indent, move right
|
||||
elif (
|
||||
re.search(r"^(?:" + tag_indent + r")", item, re.IGNORECASE | re.MULTILINE)
|
||||
re.search(
|
||||
r"^(?:" + str(config.tag_indent) + r")",
|
||||
item,
|
||||
re.IGNORECASE | re.MULTILINE | re.VERBOSE,
|
||||
)
|
||||
and is_block_raw is False
|
||||
):
|
||||
tmp = (indent * indent_level) + item + "\n"
|
||||
|
|
@ -123,7 +133,7 @@ def indent_html(rawcode):
|
|||
|
||||
# we can try to fix template tags
|
||||
tmp = re.sub(r"({[{|%]\-?)(\w[^}].+?)([}|%]})", r"\1 \2\3", tmp)
|
||||
tmp = re.sub(r"({[{|%])([^}].+?[^(?: |\-)])([}|%]})", r"\1\2 \3", tmp)
|
||||
tmp = re.sub(r"({[{|%])([^}].+?[^(?:\ |\-)])([}|%]})", r"\1\2 \3", tmp)
|
||||
tmp = re.sub(r"({[{|%])([^}].+?[^ ])(\-[}|%]})", r"\1\2 \3", tmp)
|
||||
|
||||
# handlebars templates
|
||||
|
|
@ -132,23 +142,29 @@ def indent_html(rawcode):
|
|||
# if a opening raw tag then start ignoring.. only if there is no closing tag
|
||||
# on the same line
|
||||
if (
|
||||
re.search("|".join(ignored_group_opening), item, re.IGNORECASE)
|
||||
) or re.search("|".join(ignored_block_opening), item, re.IGNORECASE):
|
||||
re.search(config.ignored_group_opening, item, re.IGNORECASE | re.VERBOSE)
|
||||
) or re.search(config.ignored_block_opening, item, re.IGNORECASE | re.VERBOSE):
|
||||
is_block_raw = True
|
||||
|
||||
# if a normal tag, we can try to expand attributes
|
||||
elif (
|
||||
format_long_attributes
|
||||
config.format_long_attributes
|
||||
and is_block_raw is False
|
||||
and len(tmp) > max_line_length
|
||||
and len(tmp) > int(config.max_line_length)
|
||||
):
|
||||
# get leading space, and attributes
|
||||
tmp = re.sub(r"(\s*?)(<\w+\s)([^>]+?)(/?>)", _format_attributes, tmp)
|
||||
func = partial(_format_attributes, config)
|
||||
tmp = re.sub(r"(\s*?)(<\w+\s)([^>]+?)(/?>)", func, tmp)
|
||||
|
||||
# turn off raw block if we hit end - for one line raw blocks
|
||||
if (
|
||||
re.search("|".join(ignored_group_closing), item, re.IGNORECASE)
|
||||
) or re.search("|".join(ignored_block_closing), item, re.IGNORECASE):
|
||||
re.search(
|
||||
re.sub(r"\s", "", config.ignored_group_closing), item, re.IGNORECASE
|
||||
)
|
||||
) or re.search(
|
||||
re.sub(r"\s", "", config.ignored_block_closing), item, re.IGNORECASE
|
||||
):
|
||||
|
||||
is_block_raw = False
|
||||
|
||||
beautified_code = beautified_code + tmp
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
"""Djlint html linter."""
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
import regex as re
|
||||
import yaml
|
||||
|
||||
from .settings import Config
|
||||
|
||||
rules = yaml.load(
|
||||
(Path(__file__).parent / "rules.yaml").read_text(encoding="utf8"),
|
||||
Loader=yaml.SafeLoader,
|
||||
|
|
@ -24,7 +27,7 @@ flags = {
|
|||
}
|
||||
|
||||
|
||||
def build_flags(flag_list):
|
||||
def build_flags(flag_list: str) -> int:
|
||||
"""Build list of regex flags."""
|
||||
split_flags = flag_list.split("|")
|
||||
|
||||
|
|
@ -34,14 +37,14 @@ def build_flags(flag_list):
|
|||
return combined_flags
|
||||
|
||||
|
||||
def get_line(start, line_ends):
|
||||
def get_line(start: int, line_ends: List) -> str:
|
||||
"""Get the line number and index of match."""
|
||||
line = list(filter(lambda pair: pair["end"] > start, line_ends))[0]
|
||||
|
||||
return "%d:%d" % (line_ends.index(line) + 1, start - line["start"])
|
||||
|
||||
|
||||
def lint_file(ignore: str, this_file: Path):
|
||||
def lint_file(config: Config, this_file: Path) -> Dict:
|
||||
"""Check file for formatting errors."""
|
||||
file_name = str(this_file)
|
||||
errors: dict = {file_name: []}
|
||||
|
|
@ -54,7 +57,7 @@ def lint_file(ignore: str, this_file: Path):
|
|||
]
|
||||
|
||||
for rule in list(
|
||||
filter(lambda x: x["rule"]["name"] not in ignore.split(","), rules)
|
||||
filter(lambda x: x["rule"]["name"] not in config.ignore.split(","), rules)
|
||||
):
|
||||
rule = rule["rule"]
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ from pathlib import Path
|
|||
from .formatter.compress_html import compress_html
|
||||
from .formatter.expand_html import expand_html
|
||||
from .formatter.indent_html import indent_html
|
||||
from .settings import Config
|
||||
|
||||
|
||||
def reformat_file(check: bool, this_file: Path):
|
||||
def reformat_file(config: Config, check: bool, this_file: Path) -> dict:
|
||||
"""Reformat html file."""
|
||||
rawcode = this_file.read_text(encoding="utf8")
|
||||
|
||||
|
|
@ -21,9 +22,9 @@ def reformat_file(check: bool, this_file: Path):
|
|||
|
||||
while itteration < 10:
|
||||
|
||||
expanded = expand_html(rawcode)
|
||||
compressed = compress_html(expanded)
|
||||
indented = indent_html(compressed)
|
||||
expanded = expand_html(rawcode, config)
|
||||
compressed = compress_html(expanded, config)
|
||||
indented = indent_html(compressed, config)
|
||||
|
||||
if (
|
||||
len(
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
flags: re.DOTALL|re.I
|
||||
patterns:
|
||||
- <(img|input|area|base|br|col|embed|hr|link|meta|param|source|track|wbr|command|keygen|menuitem|path)[^>]*?[^/]>
|
||||
- <(img|input|area|base|br|col|embed|hr|link|meta|param|source|track|wbr|command|keygen|menuitem|path)>
|
||||
- rule:
|
||||
name: W018
|
||||
message: Internal links should use the {% url ... %} pattern.
|
||||
|
|
|
|||
|
|
@ -2,234 +2,521 @@
|
|||
# pylint: disable=C0301,C0103
|
||||
# flake8: noqa
|
||||
|
||||
# default indentation
|
||||
indent = " "
|
||||
|
||||
# contents of tags will not be formatted, but tags will be formatted
|
||||
ignored_block_opening = [r"<style" r"{\*", r"<\?php", r"<script"]
|
||||
import logging
|
||||
|
||||
ignored_block_closing = [r"</style" r"\*}", r"\?>", r"</script"]
|
||||
## get pyproject.toml settings
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, Union
|
||||
|
||||
import tomlkit
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# contents of tags will not be formated and tags will not be formatted
|
||||
ignored_group_opening = [r"<!--", r"[^\{]{#", r"<pre", r"<textarea"]
|
||||
def find_pyproject(src: Path) -> Optional[Path]:
|
||||
"""Search upstream for a pyprojec.toml file."""
|
||||
|
||||
ignored_group_closing = [r"-->", r"#}", r"</pre", r"</textarea"]
|
||||
for directory in [src, *src.resolve().parents]:
|
||||
|
||||
candidate = directory / "pyproject.toml"
|
||||
|
||||
if candidate.is_file():
|
||||
return candidate
|
||||
|
||||
return None
|
||||
|
||||
|
||||
# the contents of these tag blocks will be indented, then unindented
|
||||
tag_indent = r"(?:\{\{\#)|\{% +?(if|for|block|else|spaceless|compress|addto|language|with|assets)|(?:{% 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|path|script|style|source))"
|
||||
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|path|script|style|source))"
|
||||
def load_pyproject_settings(src: Path) -> Dict:
|
||||
"""Load djlint config from pyproject.toml."""
|
||||
|
||||
# these tags should be unindented and next line will be indented
|
||||
tag_unindent_line = r"(?:\{% el)|(?:\{\{ *?(?:else|\^) *?\}\})"
|
||||
djlint_content = {}
|
||||
pyproject_file = find_pyproject(src)
|
||||
|
||||
if pyproject_file:
|
||||
content = tomlkit.parse(pyproject_file.read_text())
|
||||
try:
|
||||
djlint_content = content["tool"]["djlint"]
|
||||
except KeyError:
|
||||
logger.info("No pyproject.toml found.")
|
||||
|
||||
return djlint_content
|
||||
|
||||
|
||||
# reduce empty lines greater than x to 1 line
|
||||
reduce_extralines_gt = 2
|
||||
def build_custom_blocks(custom_blocks: Union[str, None]) -> Optional[str]:
|
||||
"""Build regex string for custom template blocks."""
|
||||
if custom_blocks:
|
||||
return "|" + "|".join(x.strip() for x in custom_blocks.split(","))
|
||||
return None
|
||||
|
||||
# if lines are longer than x
|
||||
max_line_length = 120
|
||||
format_long_attributes = True
|
||||
|
||||
# pattern used to find attributes in a tag
|
||||
attribute_pattern = r"(?:{%[^}]*?%}(?:.*?{%[^}]*?%})+?)|(?:[^\s]+?=(?:\"{{.*?}}\"|\'{{.*?}}\'))|(?:[^\s]+?=(?:\".*?\"|\'.*?\'))|required|checked|[\w|-]+|[\w|-]+=[\w|-]+|{{.*?}}"
|
||||
tag_pattern = r"(<\w+?[^>]*?)((?:\n[^>]+?)+?)(/?\>)"
|
||||
ignored_attributes = [
|
||||
"data-json",
|
||||
]
|
||||
class Config:
|
||||
"""Djling Config."""
|
||||
|
||||
ignored_paths = [
|
||||
".venv",
|
||||
"venv",
|
||||
".tox",
|
||||
".eggs",
|
||||
".git",
|
||||
".hg",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".svn",
|
||||
".bzr",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
".pants.d",
|
||||
".direnv",
|
||||
"node_modules",
|
||||
"__pypackages__",
|
||||
]
|
||||
def __init__(
|
||||
self,
|
||||
src: str,
|
||||
ignore: Optional[str] = None,
|
||||
extension: Optional[str] = None,
|
||||
quiet: Optional[bool] = False,
|
||||
):
|
||||
|
||||
start_template_tags = r"{% ?(?:if|for|block|spaceless|compress|load|assets|addto|language|with|assets)[^}]+?%}"
|
||||
self.ignored_paths: str = r"""
|
||||
\.venv
|
||||
| venv
|
||||
| \.tox
|
||||
| \.eggs
|
||||
| \.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.nox
|
||||
| \.svn
|
||||
| \.bzr
|
||||
| _build
|
||||
| buck-out
|
||||
| build
|
||||
| dist
|
||||
| \.pants\.d
|
||||
| \.direnv
|
||||
| node_modules
|
||||
| __pypackages__
|
||||
"""
|
||||
|
||||
break_template_tags = [
|
||||
r"{% ?(?:if|end|for|block|endblock|else|spaceless|compress|load|include|assets|addto|language|with|assets)[^}]+?%}",
|
||||
]
|
||||
djlint_settings = load_pyproject_settings(Path(src))
|
||||
|
||||
unformated_html_tags = ["script"]
|
||||
# custom configuration options
|
||||
self.extension: str = str(extension or djlint_settings.get("extension", "html"))
|
||||
self.ignore: str = str(ignore or djlint_settings.get("ignore", ""))
|
||||
self.quiet: str = str(quiet or djlint_settings.get("quiet", ""))
|
||||
self.custom_blocks: str = str(
|
||||
build_custom_blocks(djlint_settings.get("custom_blocks")) or ""
|
||||
)
|
||||
|
||||
ignored_blocks = [
|
||||
r"<(script|style|pre|textarea).*?(?:%s).*?</(\1)>",
|
||||
r"<!--.*?(?:%s).*?-->",
|
||||
r"{\*.*?(?:%s).*?\*}",
|
||||
r"{#.*?(?:%s).*?#}",
|
||||
r"<\?php.*?(?:%s).*?\?>",
|
||||
]
|
||||
# base options
|
||||
self.indent: str = djlint_settings.get("indent", " ")
|
||||
|
||||
ignored_inline_blocks = [
|
||||
r"<!--.*?-->",
|
||||
r"{\*.*?\*}",
|
||||
r"{#.*?#}",
|
||||
r"<\?php.*?\?>",
|
||||
]
|
||||
# contents of tags will not be formatted, but tags will be formatted
|
||||
self.ignored_block_opening: str = r"""
|
||||
<style
|
||||
| {\*
|
||||
| <\?php
|
||||
| <script
|
||||
"""
|
||||
|
||||
single_line_html_tags = [
|
||||
"button",
|
||||
"a",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"td",
|
||||
"th",
|
||||
"strong",
|
||||
"em",
|
||||
"icon",
|
||||
"span",
|
||||
"title",
|
||||
"link",
|
||||
"path",
|
||||
"label",
|
||||
"div",
|
||||
]
|
||||
self.ignored_block_closing: str = r"""
|
||||
</style
|
||||
| \*}
|
||||
| \?>
|
||||
| </script
|
||||
"""
|
||||
|
||||
always_single_line_html_tags = ["link", "img", "meta"]
|
||||
# contents of tags will not be formated and tags will not be formatted
|
||||
self.ignored_group_opening: str = r"""
|
||||
<!--
|
||||
| [^\{]{\#
|
||||
| <pre
|
||||
| <textarea
|
||||
"""
|
||||
|
||||
single_line_template_tags = ["if", "for", "block", "with"]
|
||||
self.ignored_group_closing: str = r"""
|
||||
-->
|
||||
| \#}
|
||||
| </pre
|
||||
| </textarea
|
||||
"""
|
||||
|
||||
break_html_tags = [
|
||||
"a",
|
||||
"abbr",
|
||||
"acronym",
|
||||
"address",
|
||||
"applet",
|
||||
"area",
|
||||
"article",
|
||||
"aside",
|
||||
"audio",
|
||||
"b",
|
||||
"base",
|
||||
"basefont",
|
||||
"bdi",
|
||||
"bdo",
|
||||
"big",
|
||||
"blockquote",
|
||||
"body",
|
||||
"br",
|
||||
"button",
|
||||
"canvas",
|
||||
"caption",
|
||||
"center",
|
||||
"cite",
|
||||
"code",
|
||||
"col",
|
||||
"colgroup",
|
||||
"data",
|
||||
"datalist",
|
||||
"dd",
|
||||
"del",
|
||||
"details",
|
||||
"dfn",
|
||||
"dialog",
|
||||
"dir",
|
||||
"div",
|
||||
"dl",
|
||||
"dt",
|
||||
"em",
|
||||
"embed",
|
||||
"fieldset",
|
||||
"figcaption",
|
||||
"figure",
|
||||
"font",
|
||||
"footer",
|
||||
"form",
|
||||
"frame",
|
||||
"frameset",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"head",
|
||||
"header",
|
||||
"hr",
|
||||
"html",
|
||||
"i",
|
||||
"iframe",
|
||||
"icon",
|
||||
"img",
|
||||
"input",
|
||||
"ins",
|
||||
"kbd",
|
||||
"label",
|
||||
"legend",
|
||||
"li",
|
||||
"link",
|
||||
"main",
|
||||
"map",
|
||||
"mark",
|
||||
"meta",
|
||||
"meter",
|
||||
"nav",
|
||||
"noframes",
|
||||
"noscript",
|
||||
"object",
|
||||
"ol",
|
||||
"optgroup",
|
||||
"option",
|
||||
"output",
|
||||
"p",
|
||||
"path",
|
||||
"param",
|
||||
"picture",
|
||||
"progress",
|
||||
"q",
|
||||
"rp",
|
||||
"rt",
|
||||
"ruby",
|
||||
"s",
|
||||
"samp",
|
||||
"script",
|
||||
"section",
|
||||
"select",
|
||||
"small",
|
||||
"source",
|
||||
"span",
|
||||
"strike",
|
||||
"strong",
|
||||
"style",
|
||||
"sub",
|
||||
"summary",
|
||||
"sup",
|
||||
"svg",
|
||||
"table",
|
||||
"tbody",
|
||||
"td",
|
||||
"template",
|
||||
"tfoot",
|
||||
"th",
|
||||
"thead",
|
||||
"time",
|
||||
"title",
|
||||
"tr",
|
||||
"track",
|
||||
"tt",
|
||||
"u",
|
||||
"ul",
|
||||
"var",
|
||||
"video",
|
||||
"wbr",
|
||||
]
|
||||
# the contents of these tag blocks will be indented, then unindented
|
||||
self.tag_indent: str = (
|
||||
r"""
|
||||
(?:\{\{\#|\{%)[ ]*?
|
||||
(
|
||||
if
|
||||
| for
|
||||
| block
|
||||
| else
|
||||
| spaceless
|
||||
| compress
|
||||
| addto
|
||||
| language
|
||||
| with
|
||||
| assets
|
||||
| verbatim
|
||||
| autoescape
|
||||
| comment
|
||||
| filter
|
||||
| each
|
||||
"""
|
||||
+ self.custom_blocks
|
||||
+ r"""
|
||||
)
|
||||
| (?:<
|
||||
(?:
|
||||
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
|
||||
| path
|
||||
| script
|
||||
| style
|
||||
| source
|
||||
)
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
self.tag_unindent: str = 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
|
||||
| cache
|
||||
| main
|
||||
| section
|
||||
| aside
|
||||
| footer
|
||||
| figure
|
||||
| video
|
||||
| span
|
||||
| p
|
||||
| g
|
||||
| svg
|
||||
| h\d
|
||||
| button
|
||||
| img
|
||||
| path
|
||||
| script
|
||||
| style
|
||||
| source
|
||||
)
|
||||
)
|
||||
"""
|
||||
|
||||
# these tags should be unindented and next line will be indented
|
||||
self.tag_unindent_line: str = r"""
|
||||
(?:\{%[ ]*?(?:elif|else|empty))
|
||||
| (?:
|
||||
\{\{[ ]*?
|
||||
(
|
||||
(?:else|\^)
|
||||
[ ]*?\}\}
|
||||
)
|
||||
)
|
||||
"""
|
||||
|
||||
# reduce empty lines greater than x to 1 line
|
||||
self.reduce_extralines_gt = 2
|
||||
|
||||
# if lines are longer than x
|
||||
self.max_line_length = 120
|
||||
self.format_long_attributes = True
|
||||
|
||||
# pattern used to find attributes in a tag
|
||||
self.attribute_pattern: str = r"""
|
||||
(?:{%[^}]*?%}(?:.*?{%[^}]*?%})+?)
|
||||
| (?:[^\s]+?=(?:\"{{.*?}}\"|\'{{.*?}}\'))
|
||||
| (?:[^\s]+?=(?:\".*?\"|\'.*?\'))
|
||||
| required
|
||||
| checked
|
||||
| [\w|-]+
|
||||
| [\w|-]+=[\w|-]+
|
||||
| {{.*?}}
|
||||
"""
|
||||
|
||||
self.tag_pattern: str = r"""
|
||||
(<\w+?[^>]*?)((?:\n[^>]+?)+?)(/?\>)
|
||||
"""
|
||||
|
||||
self.ignored_attributes: list = [r"""data-json"""]
|
||||
|
||||
self.start_template_tags: str = (
|
||||
r"""
|
||||
if
|
||||
| for
|
||||
| block
|
||||
| spaceless
|
||||
| compress
|
||||
| load
|
||||
| assets
|
||||
| addto
|
||||
| language
|
||||
| with
|
||||
| assets
|
||||
| autoescape
|
||||
| comment
|
||||
| filter
|
||||
| verbatim
|
||||
| each
|
||||
"""
|
||||
+ self.custom_blocks
|
||||
+ r"""
|
||||
"""
|
||||
)
|
||||
|
||||
self.break_template_tags: str = (
|
||||
r"""
|
||||
if
|
||||
| end
|
||||
| for
|
||||
| block
|
||||
| endblock
|
||||
| else
|
||||
| spaceless
|
||||
| compress
|
||||
| load
|
||||
| include
|
||||
| assets
|
||||
| addto
|
||||
| language
|
||||
| with
|
||||
| assets
|
||||
| autoescape
|
||||
| comment
|
||||
| filter
|
||||
| elif
|
||||
| resetcycle
|
||||
| verbatim
|
||||
| each
|
||||
"""
|
||||
+ self.custom_blocks
|
||||
+ r"""
|
||||
"""
|
||||
)
|
||||
|
||||
self.ignored_blocks: list = [
|
||||
r"<(script|style|pre|textarea).*?(?:%s).*?</(\1)>",
|
||||
r"<!--.*?(?:%s).*?-->",
|
||||
r"{\*.*?(?:%s).*?\*}",
|
||||
r"{\#.*?(?:%s).*?#}",
|
||||
r"<\?php.*?(?:%s).*?\?>",
|
||||
]
|
||||
|
||||
self.ignored_inline_blocks: str = r"""
|
||||
<!--.*?-->
|
||||
| {\*.*?\*}
|
||||
| {\#.*?\#}
|
||||
| <\?php.*?\?>
|
||||
"""
|
||||
|
||||
self.single_line_html_tags: str = r"""
|
||||
button
|
||||
| a
|
||||
| h1
|
||||
| h2
|
||||
| h3
|
||||
| h4
|
||||
| h5
|
||||
| h6
|
||||
| td
|
||||
| th
|
||||
| strong
|
||||
| em
|
||||
| icon
|
||||
| span
|
||||
| title
|
||||
| link
|
||||
| path
|
||||
| label
|
||||
| div
|
||||
| li
|
||||
"""
|
||||
|
||||
self.always_single_line_html_tags: str = r"""
|
||||
link
|
||||
| img
|
||||
| meta
|
||||
"""
|
||||
|
||||
self.single_line_template_tags: str = r"""
|
||||
if
|
||||
| for
|
||||
| block
|
||||
| with
|
||||
| comment
|
||||
"""
|
||||
|
||||
self.break_html_tags: str = r"""
|
||||
a
|
||||
| abbr
|
||||
| acronym
|
||||
| address
|
||||
| applet
|
||||
| area
|
||||
| article
|
||||
| aside
|
||||
| audio
|
||||
| b
|
||||
| base
|
||||
| basefont
|
||||
| bdi
|
||||
| bdo
|
||||
| big
|
||||
| blockquote
|
||||
| body
|
||||
| br
|
||||
| button
|
||||
| canvas
|
||||
| caption
|
||||
| center
|
||||
| cite
|
||||
| code
|
||||
| col
|
||||
| colgroup
|
||||
| data
|
||||
| datalist
|
||||
| dd
|
||||
| del
|
||||
| details
|
||||
| dfn
|
||||
| dialog
|
||||
| dir
|
||||
| div
|
||||
| dl
|
||||
| dt
|
||||
| em
|
||||
| embed
|
||||
| fieldset
|
||||
| figcaption
|
||||
| figure
|
||||
| font
|
||||
| footer
|
||||
| form
|
||||
| frame
|
||||
| frameset
|
||||
| h1
|
||||
| h2
|
||||
| h3
|
||||
| h4
|
||||
| h5
|
||||
| h6
|
||||
| head
|
||||
| header
|
||||
| hr
|
||||
| html
|
||||
| i
|
||||
| iframe
|
||||
| icon
|
||||
| img
|
||||
| input
|
||||
| ins
|
||||
| kbd
|
||||
| label
|
||||
| legend
|
||||
| li
|
||||
| link
|
||||
| main
|
||||
| map
|
||||
| mark
|
||||
| meta
|
||||
| meter
|
||||
| nav
|
||||
| noframes
|
||||
| noscript
|
||||
| object
|
||||
| ol
|
||||
| optgroup
|
||||
| option
|
||||
| output
|
||||
| p
|
||||
| path
|
||||
| param
|
||||
| picture
|
||||
| progress
|
||||
| q
|
||||
| rp
|
||||
| rt
|
||||
| ruby
|
||||
| s
|
||||
| samp
|
||||
| script
|
||||
| section
|
||||
| select
|
||||
| small
|
||||
| source
|
||||
| span
|
||||
| strike
|
||||
| strong
|
||||
| style
|
||||
| sub
|
||||
| summary
|
||||
| sup
|
||||
| svg
|
||||
| table
|
||||
| tbody
|
||||
| td
|
||||
| template
|
||||
| tfoot
|
||||
| th
|
||||
| thead
|
||||
| time
|
||||
| title
|
||||
| tr
|
||||
| track
|
||||
| tt
|
||||
| u
|
||||
| ul
|
||||
| var
|
||||
| video
|
||||
| wbr
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in a new issue