| 50 | } |
| 51 | |
| 52 | func convertJSONToHTML(outputFile string) error { |
| 53 | htmlFile, err := os.Create(outputFile) |
| 54 | if err != nil { |
| 55 | return fmt.Errorf("failed to create output file: %v", err) |
| 56 | } |
| 57 | defer htmlFile.Close() |
| 58 | |
| 59 | const tmpl = `<!DOCTYPE html> |
| 60 | <html> |
| 61 | <head> |
| 62 | <meta charset="UTF-8"> |
| 63 | <title>HTTPX Report</title> |
| 64 | <style> |
| 65 | * { box-sizing: border-box; margin: 0; padding: 0; } |
| 66 | body { |
| 67 | font-family: 'Courier New', monospace; |
| 68 | background: #282a36; |
| 69 | color: #f8f8f2; |
| 70 | padding: 20px; |
| 71 | } |
| 72 | h1 { color: #50fa7b; margin-bottom: 16px; font-size: 1.4rem; } |
| 73 | |
| 74 | /* Summary bar */ |
| 75 | .summary { |
| 76 | display: flex; |
| 77 | gap: 12px; |
| 78 | flex-wrap: wrap; |
| 79 | margin-bottom: 20px; |
| 80 | } |
| 81 | .stat { |
| 82 | background: #44475a; |
| 83 | border-radius: 6px; |
| 84 | padding: 10px 18px; |
| 85 | text-align: center; |
| 86 | min-width: 90px; |
| 87 | } |
| 88 | .stat .num { font-size: 1.6rem; font-weight: bold; } |
| 89 | .stat .lbl { font-size: 0.7rem; color: #6272a4; margin-top: 2px; } |
| 90 | .stat.total .num { color: #f8f8f2; } |
| 91 | .stat.s2xx .num { color: #50fa7b; } |
| 92 | .stat.s3xx .num { color: #f1fa8c; } |
| 93 | .stat.s4xx .num { color: #ffb86c; } |
| 94 | .stat.s5xx .num { color: #ff5555; } |
| 95 | |
| 96 | /* Search */ |
| 97 | input[type="text"] { |
| 98 | padding: 8px 12px; |
| 99 | margin-bottom: 14px; |
| 100 | width: 320px; |
| 101 | border: 1px solid #6272a4; |
| 102 | border-radius: 4px; |
| 103 | background: #44475a; |
| 104 | color: #f8f8f2; |
| 105 | font-family: inherit; |
| 106 | } |
| 107 | input[type="text"]::placeholder { color: #6272a4; } |
| 108 | |
| 109 | /* Table */ |