djLint/src/djlint/helpers.py
Christopher Pickering 215bd23190
fix(h006): prevented false positives on H006
Also other linter rules where the the error match partially overlaps the ignored block.

closes #344, closes #333
2022-08-24 09:37:42 -05:00

161 lines
4.7 KiB
Python

"""Collection of shared djLint functions."""
import regex as re
from .settings import Config
def is_ignored_block_opening(config: Config, item: str) -> bool:
"""Find ignored group opening.
A valid ignored group opening tag will not be part of a
single line block.
"""
last_index = 0
inline = list(
re.finditer(
config.ignored_blocks,
item,
flags=re.IGNORECASE | re.VERBOSE | re.MULTILINE | re.DOTALL,
)
)
if inline:
last_index = inline[
-1
].end() # get the last index. The ignored opening should start after this.
return bool(
re.search(
re.compile(config.ignored_block_opening, re.IGNORECASE | re.VERBOSE),
item[last_index:],
)
)
def is_ignored_block_closing(config: Config, item: str) -> bool:
"""Find ignored group closing.
A valid ignored group closing tag will not be part of a
single line block.
"""
last_index = 0
inline = list(
re.finditer(
re.compile(config.ignored_inline_blocks, flags=re.IGNORECASE | re.VERBOSE),
item,
)
)
if inline:
last_index = inline[
-1
].end() # get the last index. The ignored opening should start after this.
return re.search(
re.compile(config.ignored_block_closing, flags=re.IGNORECASE | re.VERBOSE),
item[last_index:],
)
def is_safe_closing_tag(config: Config, item: str) -> bool:
"""Find ignored group opening.
A valid ignored group opening tag will not be part of a
single line block.
"""
last_index = 0
inline = list(
re.finditer(
re.compile(
config.ignored_inline_blocks + r" | " + config.ignored_blocks,
flags=re.IGNORECASE | re.VERBOSE | re.MULTILINE | re.DOTALL,
),
item,
)
)
if inline:
last_index = inline[
-1
].end() # get the last index. The ignored opening should start after this.
return re.search(
re.compile(config.safe_closing_tag, flags=re.IGNORECASE | re.VERBOSE),
item[last_index:],
)
def inside_ignored_block(config: Config, html: str, match: re.Match) -> bool:
"""Do not add whitespace if the tag is in a non indent block."""
return any(
ignored_match.start(0) <= match.start() and match.end(0) <= ignored_match.end()
for ignored_match in list(
re.finditer(
re.compile(
config.ignored_blocks,
re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE | re.DOTALL,
),
html,
)
)
+ list(
re.finditer(
re.compile(config.ignored_inline_blocks, re.IGNORECASE | re.VERBOSE),
html,
)
)
)
def overlaps_ignored_block(config: Config, html: str, match: re.Match) -> bool:
"""Do not add whitespace if the tag is in a non indent block."""
return any(
# don't require the match to be fully inside the ignored block.
# poorly build html will probably span ignored blocks and should be ignored.
(
ignored_match.start(0) <= match.start()
and match.start() <= ignored_match.end()
)
or (
ignored_match.start(0) <= match.end() and match.end() <= ignored_match.end()
)
for ignored_match in list(
re.finditer(
re.compile(
config.ignored_blocks,
re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE | re.DOTALL,
),
html,
)
)
+ list(
re.finditer(
re.compile(config.ignored_inline_blocks, re.IGNORECASE | re.VERBOSE),
html,
)
)
)
def inside_ignored_rule(config: Config, html: str, match: re.Match, rule: str) -> bool:
"""Check if match is inside an ignored pattern."""
for rule_regex in config.ignored_rules:
for ignored_match in list(
re.finditer(
re.compile(rule_regex, re.DOTALL | re.IGNORECASE | re.VERBOSE),
html,
)
):
if (
rule in list(set(re.split(r"\s|,", ignored_match.group(1).strip())))
and (
ignored_match.start(0) <= match.start()
and match.start() <= ignored_match.end()
)
or (
ignored_match.start(0) <= match.end()
and match.end() <= ignored_match.end()
)
):
return True
return False