feat: report --diff-only — colored terminal diff view
Shows only the changed parts of the latest report: text diffs with ANSI colors (+green/-red/@cyan), new/missing URLs, link diffs, hidden content, meta-refresh and inline script findings. Colors are suppressed when stdout is not a terminal (pipes, log files). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fe61b18906
commit
2c3aa60d97
1 changed files with 87 additions and 4 deletions
|
|
@ -1061,8 +1061,83 @@ def cmd_approve(args: argparse.Namespace, cfg: dict) -> int:
|
|||
return 1
|
||||
|
||||
|
||||
def _print_diff_only(report: dict) -> None:
|
||||
"""Print a compact colored diff view of the latest report."""
|
||||
a = report.get("assessment", {})
|
||||
d = report.get("diff", {})
|
||||
level = a.get("level", "green")
|
||||
symbol, _ = ampel(level)
|
||||
use_color = sys.stdout.isatty()
|
||||
|
||||
if use_color:
|
||||
C = {"add": "\033[32m", "del": "\033[31m", "hdr": "\033[36m",
|
||||
"url": "\033[1;34m", "rst": "\033[0m"}
|
||||
else:
|
||||
C = {k: "" for k in ("add", "del", "hdr", "url", "rst")}
|
||||
|
||||
print(f"{symbol} Level: {level.upper()} Score: {a.get('score', 0)}")
|
||||
print()
|
||||
|
||||
for domain in d.get("new_external_domains", []):
|
||||
print(f"{C['del']}+ Neue externe Domain: {domain}{C['rst']}")
|
||||
for url in d.get("new_internal_urls", []):
|
||||
print(f"{C['add']}+ Neue URL: {url}{C['rst']}")
|
||||
for url in d.get("missing_internal_urls", []):
|
||||
print(f"{C['del']}- Fehlende URL: {url}{C['rst']}")
|
||||
for entry in d.get("new_broken_urls", []):
|
||||
print(f"{C['del']}! Neuer kaputt Link [{entry['status']}]: {entry['url']}{C['rst']}")
|
||||
|
||||
has_page_diffs = False
|
||||
for pd in d.get("page_diffs", []):
|
||||
text_diff = pd.get("text_diff", [])
|
||||
link_diff = pd.get("link_diff", {})
|
||||
new_hidden = pd.get("new_hidden_content", [])
|
||||
new_refresh = pd.get("new_meta_refresh", [])
|
||||
new_scripts = pd.get("new_inline_scripts", [])
|
||||
new_comments = pd.get("new_comment_links", [])
|
||||
if not (text_diff or link_diff or new_hidden or new_refresh
|
||||
or new_scripts or new_comments or pd.get("canonical_changed")):
|
||||
continue
|
||||
has_page_diffs = True
|
||||
print(f"\n{C['url']}{'─' * 4} {pd['url']} {'─' * 4}{C['rst']}")
|
||||
for line in text_diff:
|
||||
if line.startswith("+"):
|
||||
print(f"{C['add']}{line}{C['rst']}")
|
||||
elif line.startswith("-"):
|
||||
print(f"{C['del']}{line}{C['rst']}")
|
||||
elif line.startswith("@"):
|
||||
print(f"{C['hdr']}{line}{C['rst']}")
|
||||
else:
|
||||
print(line)
|
||||
for ltype, ld in link_diff.items():
|
||||
for added in ld.get("added", []):
|
||||
print(f"{C['add']}+ [{ltype}] {added}{C['rst']}")
|
||||
for removed in ld.get("removed", []):
|
||||
print(f"{C['del']}- [{ltype}] {removed}{C['rst']}")
|
||||
for h in new_hidden:
|
||||
print(f"{C['del']}! Hidden Content ({h.get('type')}): "
|
||||
f"{', '.join(h.get('indicators', []))}{C['rst']}")
|
||||
for mr in new_refresh:
|
||||
print(f"{C['del']}! Meta-Refresh → {mr}{C['rst']}")
|
||||
if pd.get("canonical_changed"):
|
||||
print(f"{C['del']}! Canonical: {pd.get('old_canonical')} → {pd.get('new_canonical')}{C['rst']}")
|
||||
for s in new_scripts:
|
||||
print(f"{C['del']}! Inline-Script: {', '.join(s.get('patterns', []))}{C['rst']}")
|
||||
for cl in new_comments:
|
||||
print(f"{C['del']}! Kommentar-Link: {cl}{C['rst']}")
|
||||
|
||||
nothing = (
|
||||
not d.get("new_external_domains")
|
||||
and not d.get("new_internal_urls")
|
||||
and not d.get("missing_internal_urls")
|
||||
and not d.get("new_broken_urls")
|
||||
and not has_page_diffs
|
||||
)
|
||||
if nothing:
|
||||
print("Keine Änderungen.")
|
||||
|
||||
|
||||
def cmd_report(args: argparse.Namespace, cfg: dict) -> int:
|
||||
fmt = getattr(args, "format", "md")
|
||||
rd = Path(cfg["reports_dir"])
|
||||
if not rd.exists():
|
||||
print("Noch keine Reports vorhanden.")
|
||||
|
|
@ -1074,11 +1149,17 @@ def cmd_report(args: argparse.Namespace, cfg: dict) -> int:
|
|||
return 0
|
||||
|
||||
latest = dirs[-1]
|
||||
if fmt == "json":
|
||||
p = latest / "report.json"
|
||||
else:
|
||||
p = latest / "report.md"
|
||||
|
||||
if getattr(args, "diff_only", False):
|
||||
p = latest / "report.json"
|
||||
if not p.exists():
|
||||
print(f"Report-Datei nicht gefunden: {p}", file=sys.stderr)
|
||||
return 1
|
||||
_print_diff_only(json.loads(p.read_text(encoding="utf-8")))
|
||||
return 0
|
||||
|
||||
fmt = getattr(args, "format", "md")
|
||||
p = latest / ("report.json" if fmt == "json" else "report.md")
|
||||
if not p.exists():
|
||||
print(f"Report-Datei nicht gefunden: {p}", file=sys.stderr)
|
||||
return 1
|
||||
|
|
@ -1379,6 +1460,8 @@ def _build_parser() -> argparse.ArgumentParser:
|
|||
|
||||
rp = sub.add_parser("report", help="Letzten Report anzeigen")
|
||||
rp.add_argument("--format", choices=["md", "json"], default="md")
|
||||
rp.add_argument("--diff-only", action="store_true",
|
||||
help="Nur Textdiffs geänderter Seiten anzeigen (farbig)")
|
||||
|
||||
sub.add_parser("status", help="Übersichtsstatus anzeigen")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue