github.com/jgbaldwinbrown/perf@v0.1.1/benchstat/html.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package benchstat 6 7 import ( 8 "bytes" 9 "strings" 10 11 "github.com/google/safehtml" 12 "github.com/google/safehtml/template" 13 ) 14 15 var htmlTemplate = template.Must(template.New("").Funcs(htmlFuncs).Parse(` 16 {{- if . -}} 17 {{with index . 0}} 18 <table class='benchstat {{if .OldNewDelta}}oldnew{{end}}'> 19 {{if eq (len .Configs) 1}} 20 {{- else -}} 21 <tr class='configs'><th>{{range .Configs}}<th>{{.}}{{end}} 22 {{end}} 23 {{end}} 24 {{- range $i, $table := .}} 25 <tbody> 26 {{if eq (len .Configs) 1}} 27 <tr><th><th>{{.Metric}} 28 {{else -}} 29 <tr><th><th colspan='{{len .Configs}}' class='metric'>{{.Metric}}{{if .OldNewDelta}}<th>delta{{end}} 30 {{end}}{{range $group := group $table.Rows -}} 31 {{if and (gt (len $table.Groups) 1) (len (index . 0).Group)}}<tr class='group'><th colspan='{{colspan (len $table.Configs) $table.OldNewDelta}}'>{{(index . 0).Group}}{{end}} 32 {{- range $row := . -}} 33 {{if $table.OldNewDelta -}} 34 <tr class='{{if eq .Change 1}}better{{else if eq .Change -1}}worse{{else}}unchanged{{end}}'> 35 {{- else -}} 36 <tr> 37 {{- end -}} 38 <td>{{.Benchmark}}{{range .Metrics}}<td>{{.Format $row.Scaler}}{{end}}{{if $table.OldNewDelta}}<td class='{{if eq .Delta "~"}}nodelta{{else}}delta{{end}}'>{{replace .Delta "-" "−" -1}}<td class='note'>{{.Note}}{{end}} 39 {{end -}} 40 {{- end -}} 41 <tr><td> 42 </tbody> 43 {{end}} 44 </table> 45 {{end -}} 46 `)) 47 48 var htmlFuncs = template.FuncMap{ 49 "replace": strings.Replace, 50 "group": htmlGroup, 51 "colspan": htmlColspan, 52 } 53 54 func htmlColspan(configs int, delta bool) int { 55 if delta { 56 configs++ 57 } 58 return configs + 1 59 } 60 61 func htmlGroup(rows []*Row) (out [][]*Row) { 62 var group string 63 var cur []*Row 64 for _, r := range rows { 65 if r.Group != group { 66 group = r.Group 67 if len(cur) > 0 { 68 out = append(out, cur) 69 cur = nil 70 } 71 } 72 cur = append(cur, r) 73 } 74 if len(cur) > 0 { 75 out = append(out, cur) 76 } 77 return 78 } 79 80 // SafeFormatHTML returns the HTML formatting of the tables. 81 func SafeFormatHTML(tables []*Table) safehtml.HTML { 82 h, err := htmlTemplate.ExecuteToHTML(tables) 83 if err != nil { 84 // Only possible errors here are template not matching data structure. 85 // Don't make caller check - it's our fault. 86 panic(err) 87 } 88 return h 89 } 90 91 // FormatHTML appends an HTML formatting of the tables to buf. 92 func FormatHTML(buf *bytes.Buffer, tables []*Table) { 93 err := htmlTemplate.Execute(buf, tables) 94 if err != nil { 95 // Only possible errors here are template not matching data structure. 96 // Don't make caller check - it's our fault. 97 panic(err) 98 } 99 }