()
| 140 | |
| 141 | |
| 142 | def main() -> None: |
| 143 | args = parse_args() |
| 144 | alerts = load_alerts(args.input) |
| 145 | counts = {"error": 0, "warning": 0, "suggestion": 0} |
| 146 | for alert in alerts: |
| 147 | if not isinstance(alert, dict): |
| 148 | continue |
| 149 | severity = str(alert.get("Severity", "")).lower() |
| 150 | if severity in counts: |
| 151 | counts[severity] += 1 |
| 152 | args.output.parent.mkdir(parents=True, exist_ok=True) |
| 153 | table_rows = render_alert_rows(alerts) |
| 154 | html_content = f""" |
| 155 | <!DOCTYPE html> |
| 156 | <html lang="en"> |
| 157 | <head> |
| 158 | <meta charset="utf-8" /> |
| 159 | <title>Vale Report</title> |
| 160 | <style> |
| 161 | body {{ font-family: Arial, sans-serif; margin: 2rem; }} |
| 162 | table {{ border-collapse: collapse; width: 100%; }} |
| 163 | th, td {{ border: 1px solid #ccc; padding: 0.5rem; text-align: left; }} |
| 164 | th {{ background-color: #f0f0f0; }} |
| 165 | tbody tr:nth-child(even) {{ background-color: #fafafa; }} |
| 166 | .severity-error {{ color: #c62828; font-weight: bold; }} |
| 167 | .severity-warning {{ color: #ef6c00; font-weight: bold; }} |
| 168 | .severity-suggestion {{ color: #1565c0; font-weight: bold; }} |
| 169 | </style> |
| 170 | </head> |
| 171 | <body> |
| 172 | <h1>Vale Report</h1> |
| 173 | <p>Total alerts: {len(alerts)}</p> |
| 174 | <ul> |
| 175 | <li>Errors: {counts['error']}</li> |
| 176 | <li>Warnings: {counts['warning']}</li> |
| 177 | <li>Suggestions: {counts['suggestion']}</li> |
| 178 | </ul> |
| 179 | <table> |
| 180 | <thead> |
| 181 | <tr> |
| 182 | <th>File</th> |
| 183 | <th>Line</th> |
| 184 | <th>Column</th> |
| 185 | <th>Severity</th> |
| 186 | <th>Rule</th> |
| 187 | <th>Message</th> |
| 188 | </tr> |
| 189 | </thead> |
| 190 | <tbody> |
| 191 | {table_rows} |
| 192 | </tbody> |
| 193 | </table> |
| 194 | </body> |
| 195 | </html> |
| 196 | """ |
| 197 | args.output.write_text(html_content, encoding="utf-8") |
| 198 | |
| 199 |
no test coverage detected