github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/web/template_helpers.go (about) 1 package web 2 3 import ( 4 "crypto/md5" 5 "encoding/json" 6 "fmt" 7 "html/template" 8 "io" 9 "reflect" 10 "regexp" 11 "strings" 12 13 "github.com/evergreen-ci/evergreen" 14 "github.com/evergreen-ci/evergreen/util" 15 ) 16 17 type timePeriod struct { 18 secs int 19 unit string 20 units string 21 unitShort string 22 } 23 24 var Chunks = []timePeriod{ 25 {60 * 60 * 24, "day", "days", "d"}, 26 {60 * 60, "hour", "hours", "h"}, 27 {60, "min", "min", "m"}, 28 {1, "sec", "sec", "s"}, 29 } 30 31 // Because Go's templating language for some reason doesn't allow assignments, 32 // use this to get around it. 33 type MutableVar struct { 34 Value interface{} 35 } 36 37 func (self *MutableVar) Get() interface{} { 38 return self.Value 39 } 40 41 func (self *MutableVar) Set(v interface{}) interface{} { 42 self.Value = v 43 return "" 44 } 45 46 //Create function Mappings - Add functions here to 47 //make them usable in the template language 48 func MakeCommonFunctionMap(settings *evergreen.Settings) (template.FuncMap, 49 error) { 50 funcs := map[string]interface{}{} 51 52 //Equals function 53 funcs["Eq"] = reflect.DeepEqual 54 55 //Greater than function, with an optional threshold 56 funcs["Gte"] = func(a, b, threshold int) bool { 57 return a+threshold >= b 58 } 59 60 //Convenience function for ternary operator in templates 61 // condition ? iftrue : otherwise 62 funcs["Tern"] = func(condition bool, iftrue interface{}, otherwise interface{}) interface{} { 63 if condition { 64 return iftrue 65 } 66 return otherwise 67 } 68 69 // Unescape HTML. Be very careful that you don't pass any user input through 70 // this, that would be an XSS vulnerability. 71 funcs["Unescape"] = func(s string) interface{} { 72 return template.HTML(s) 73 } 74 75 // return the base name for a file 76 funcs["Basename"] = func(str string) string { 77 lastSlash := strings.LastIndex(str, "/") 78 if lastSlash == -1 || lastSlash == len(str)-1 { 79 // try to find the index using windows-style filesystem separators 80 lastSlash = strings.LastIndex(str, "\\") 81 if lastSlash == -1 || lastSlash == len(str)-1 { 82 return str 83 } 84 } 85 return str[lastSlash+1:] 86 } 87 88 // Get 50x50 Gravatar profile pic URL for given email 89 funcs["Gravatar"] = func(email string) string { 90 h := md5.New() 91 io.WriteString(h, email) 92 93 return fmt.Sprintf("http://www.gravatar.com/avatar/%x?s=50", h.Sum(nil)) 94 } 95 96 // jsonifying 97 funcs["Json"] = func(obj interface{}) (string, error) { 98 v, err := json.Marshal(obj) 99 if err != nil { 100 return "", err 101 } 102 uninterpolateLeft := strings.Replace(string(v), "[[", "[[", -1) 103 uninterpolateRight := strings.Replace(uninterpolateLeft, "]]", "]]", -1) 104 return uninterpolateRight, nil 105 } 106 107 //Truncate a string to the desired length. 108 funcs["Trunc"] = util.Truncate 109 110 funcs["IsProd"] = func() bool { 111 return settings.IsProd 112 } 113 114 /* Unpleasant hack to make Go's templating language support assignments */ 115 funcs["MutableVar"] = func() interface{} { 116 return &MutableVar{""} 117 } 118 119 //A map of systemwide globals, set up only once, which can be accessed via 120 //template function for usage on the front-end. 121 GLOBALS := make(map[string]string) 122 GLOBALS["revision"] = "none" //evergreen.GetCurrentRevision() 123 GLOBALS["uiUrl"] = settings.Ui.Url 124 funcs["Global"] = func(key string) string { 125 val, present := GLOBALS[key] 126 if !present { 127 return "" 128 } else { 129 return val 130 } 131 } 132 133 // Remove ANSI color sequences in cases where it doesn't make sense to include 134 // them, e.g. raw task logs 135 funcs["RemoveANSI"] = func(line string) string { 136 re, err := regexp.Compile("\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]") 137 if err != nil { 138 return "" 139 } 140 return re.ReplaceAllString(line, "") 141 } 142 143 return funcs, nil 144 }