from __future__ import annotations import re import unicodedata from html import escape from urllib.parse import quote from .models import ScanReport INVALID_FILENAME_CHARS = re.compile(r'[\x00-\x1f\x7f<>:"/\\|?*]') REPORT_MARK = """""" def safe_report_filename(repository_name: str, extension: str) -> str: cleaned = INVALID_FILENAME_CHARS.sub("_", repository_name).strip(" .") cleaned = cleaned[:100].rstrip(" .") or "repository" return f"repopulse-{cleaned}.{extension}" def content_disposition(filename: str) -> str: fallback = unicodedata.normalize("NFKD", filename).encode("ascii", "ignore").decode("ascii") fallback = INVALID_FILENAME_CHARS.sub("_", fallback).strip(" .") or "repopulse-report" return f"attachment; filename=\"{fallback}\"; filename*=UTF-8''{quote(filename, safe='')}" def render_html_report(report: ScanReport) -> str: category_rows = "".join( f"{escape(name)}{score}/100" for name, score in report.category_scores.items() ) finding_rows = "".join( "" f"{escape(item.severity.value)}" f"{escape(item.category)}" f"{escape(item.message)}" f"{escape(item.path or '')}{':' + str(item.line) if item.line else ''}" "" for item in report.findings ) hotspot_rows = "".join( "" f"{escape(item.path)}{escape(item.language)}" f"{item.score}{item.lines_of_code}{item.churn}" "" for item in report.hotspots[:25] ) return f""" RepoPulse report — {escape(report.repository_name)}
{REPORT_MARK}RepoPulseRepository intelligence

Deterministic repository intelligence report

{escape(report.repository_name)}

{escape(report.repository_path)} · {escape(report.scanned_at.isoformat())}

{report.health_score}
{escape(report.release_readiness)}
{report.metrics.source_files}
source files
{report.metrics.lines_of_code}
LOC
{report.metrics.test_files}
test files
{len(report.findings)}
findings

Category scores

{category_rows}

Hotspots

{hotspot_rows}
PathLanguageScoreLOCChurn

Findings

{finding_rows}
SeverityCategoryFindingLocation
"""