added rule H025, closes #58

This commit is contained in:
Christopher Pickering 2021-10-06 15:00:08 +02:00
parent 569f9112ac
commit b8562e463a
No known key found for this signature in database
GPG key ID: E14DB3B0A0FACF84
4 changed files with 71 additions and 17 deletions

View file

@ -8,13 +8,14 @@ Next Release
- Added rule H022 to find http links
- Added rule H023 to find entity references
- Added rule H024 to find type on scripts and styles
- Added rule H025 to check for orphan tags. Thanks to https://stackoverflow.com/a/1736801/10265880
- Improved attribute formatting
- Updated ``blank_line_after_tag`` option to add newline regardless of location
- Fixed django ``trans`` tag formatting
- Added formatting for inline styles
- Added formatting for template conditions inside attributes
- Added srcset as possible url location in linter rules
- Special thanks to `jayvdb <https://github.com/jayvdb>`_
0.5.3
-----
- Change stdout for ``--reformat/check`` options to only print new html when using stdin as the input

View file

@ -1,4 +1,5 @@
"""Djlint html linter."""
import copy
from pathlib import Path
from typing import Dict, List
@ -69,20 +70,59 @@ def lint_file(config: Config, this_file: Path) -> Dict:
for pattern in rule["patterns"]:
for match in re.finditer(
re.compile(pattern, flags=build_flags(rule.get("flags", "re.DOTALL"))),
html,
):
# rule H025 is a special case where the output must be an even num.
if rule["name"] == "H025":
open_tags = []
if _should_ignore(config, html, match) is False:
errors[file_name].append(
{
"code": rule["name"],
"line": get_line(match.start(), line_ends),
"match": match.group().strip()[:20],
"message": rule["message"],
}
)
for match in re.finditer(
re.compile(
pattern, flags=build_flags(rule.get("flags", "re.DOTALL"))
),
html,
):
# close tags should equal open tags
if match.group(1).split(" ")[0][0] != "/":
open_tags.append(match)
else:
for i, tag in enumerate(copy.deepcopy(open_tags)):
if (
tag.group(1).split(" ")[0]
== match.group(1).split(" ")[0][1:]
):
open_tags.pop(i)
break
else:
# there was no open tag matching the close tag
open_tags.append(match)
for match in open_tags:
if _should_ignore(config, html, match) is False:
errors[file_name].append(
{
"code": rule["name"],
"line": get_line(match.start(), line_ends),
"match": match.group().strip()[:20],
"message": rule["message"],
}
)
else:
for match in re.finditer(
re.compile(
pattern, flags=build_flags(rule.get("flags", "re.DOTALL"))
),
html,
):
if _should_ignore(config, html, match) is False:
errors[file_name].append(
{
"code": rule["name"],
"line": get_line(match.start(), line_ends),
"match": match.group().strip()[:20],
"message": rule["message"],
}
)
# remove duplicate matches
for file_name, error_dict in errors.items():

View file

@ -299,3 +299,8 @@
flags: re.I
patterns:
- <(?:script|style)[^>]*?type=["|'][^>]*?>
- rule:
name: H025
message: Tag seems to be an orphan.
patterns:
- <((?:\"[^\"<>]*\"['\"]*|'[^'<>]*'['\"]*|[^'\"<>])+)(?<!/\s*)>

View file

@ -7,7 +7,7 @@ run::
# for a single test
pytest tests/test_linter.py::test_H021 --cov=src/djlint --cov-branch \
pytest tests/test_linter.py::test_H012 --cov=src/djlint --cov-branch \
--cov-report xml:coverage.xml --cov-report term-missing
"""
@ -152,6 +152,7 @@ def test_H012(runner: CliRunner, tmp_file: TextIO) -> None:
b"<p>{% if activity.reporting_groups|length <= 0 %}<h3>{% trans 'General' %}</h3>{% endif %}</p>",
)
result = runner.invoke(djlint, [tmp_file.name])
print(result.output)
assert result.exit_code == 0
assert "H012 1:" not in result.output
@ -203,7 +204,7 @@ def test_H017(runner: CliRunner, tmp_file: TextIO) -> None:
assert "H017 1:" in result.output
# test colgroup tag
write_to_file(tmp_file.name, b"<colgroup><colgroup asdf>")
write_to_file(tmp_file.name, b"<colgroup><colgroup asdf></colgroup></colgroup>")
result = runner.invoke(djlint, [tmp_file.name])
assert result.exit_code == 0
assert "H017 1:" not in result.output
@ -212,7 +213,7 @@ def test_H017(runner: CliRunner, tmp_file: TextIO) -> None:
def test_DJ018(runner: CliRunner, tmp_file: TextIO) -> None:
write_to_file(
tmp_file.name,
b'<a href="/Collections?handler=RemoveAgreement&id=@a.Id">\n<form action="/Collections">',
b'<a href="/Collections?handler=RemoveAgreement&id=@a.Id">\n<form action="/Collections"></form></a>',
)
result = runner.invoke(djlint, [tmp_file.name])
assert result.exit_code == 1
@ -306,6 +307,13 @@ def test_H024(runner: CliRunner, tmp_file: TextIO) -> None:
assert "H024 1:" in result.output
def test_H025(runner: CliRunner, tmp_file: TextIO) -> None:
write_to_file(tmp_file.name, b"<div>")
result = runner.invoke(djlint, [tmp_file.name])
assert result.exit_code == 1
assert "H025 1:" in result.output
def test_rules_not_matched_in_ignored_block(
runner: CliRunner, tmp_file: TextIO
) -> None: