from datetime import datetime
from typing import Any
from jinja2 import Template
from src.formatters.base import BaseFormatter
HTML_TEMPLATE = """
Git Insights Report
Generated: {{ timestamp }}
{% if commit_analysis %}
Commit Analysis
{{ commit_analysis.total_commits }}
Total Commits
{{ commit_analysis.unique_authors }}
Authors
{{ "%.1f"|format(commit_analysis.average_commits_per_day) }}
Avg/Day
Top Contributors
| Author | Commits | Lines + | Lines - |
{% for author in commit_analysis.top_authors[:5] %}
| {{ author.name }} |
{{ author.commit_count }} |
{{ author.lines_added }} |
{{ author.lines_deleted }} |
{% endfor %}
{% endif %}
{% if velocity_analysis %}
Velocity Analysis
{{ velocity_analysis.commits_per_day }}
Commits/Day
{{ velocity_analysis.commits_per_week }}
Commits/Week
{{ velocity_analysis.velocity_trend|capitalize }}
Trend
{% endif %}
{% if code_churn_analysis %}
Code Churn
+{{ code_churn_analysis.total_lines_added }}
Lines Added
-{{ code_churn_analysis.total_lines_deleted }}
Lines Deleted
{{ code_churn_analysis.net_change }}
Net Change
{% endif %}
{% if risky_commit_analysis and risky_commit_analysis.total_risky > 0 %}
Risky Commits
{{ risky_commit_analysis.total_risky }} potentially risky commits detected
{% if risky_commit_analysis.large_commits %}
Large Commits ({{ risky_commit_analysis.large_commits|length }})
| SHA | Author | Changes |
{% for commit in risky_commit_analysis.large_commits[:5] %}
| {{ commit.sha }} |
{{ commit.author_name }} |
+{{ commit.additions }} / -{{ commit.deletions }} |
{% endfor %}
{% endif %}
{% endif %}
"""
class HTMLFormatter(BaseFormatter):
"""HTML output formatter."""
@staticmethod
def format(data: Any) -> str:
"""Format data as HTML."""
template = Template(HTML_TEMPLATE)
return template.render(
timestamp=datetime.now().isoformat(),
commit_analysis=getattr(data, "commit_analysis", None),
velocity_analysis=getattr(data, "velocity_analysis", None),
code_churn_analysis=getattr(data, "code_churn_analysis", None),
risky_commit_analysis=getattr(data, "risky_commit_analysis", None),
)