github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/service/templatefuncs.go (about) 1 package service 2 3 import ( 4 "crypto/md5" 5 "fmt" 6 "io" 7 "net/url" 8 "regexp" 9 "time" 10 11 "github.com/evergreen-ci/evergreen/model/user" 12 "github.com/evergreen-ci/evergreen/util" 13 "github.com/gorilla/mux" 14 "github.com/mongodb/grip" 15 "github.com/pkg/errors" 16 ) 17 18 const defaultHelpURL = "https://github.com/evergreen-ci/evergreen/wiki/How-To-Read-Evergreen" 19 20 // FuncOptions are global variables injected into our templating functions. 21 type FuncOptions struct { 22 WebHome string 23 HelpHome string 24 IsProd bool 25 Router *mux.Router 26 } 27 28 // MutableVar is a setable variable for UI templates. 29 // This utility allows us to set and retrieve values, which 30 // is not a built in feature of Go HTML templates. 31 type MutableVar struct { 32 Value interface{} 33 } 34 35 // Get returns the value of the variable. 36 func (self *MutableVar) Get() interface{} { 37 return self.Value 38 } 39 40 // Set sets the value of the variable. 41 // Set returns the empty string so as to not pollute the resulting template. 42 func (self *MutableVar) Set(v interface{}) interface{} { 43 self.Value = v 44 return "" 45 } 46 47 // MakeTemplateFuncs creates and registers all of our built-in template functions. 48 func MakeTemplateFuncs(fo FuncOptions, superUsers []string) (map[string]interface{}, error) { 49 r := map[string]interface{}{ 50 // IsSuperUser returns true if the given user Id has super user privileges. 51 "IsSuperUser": func(userName string) bool { 52 return len(superUsers) == 0 || util.SliceContains(superUsers, userName) 53 }, 54 // Gravatar returns a Gravatar URL for the given email string. 55 "Gravatar": func(email string) string { 56 h := md5.New() 57 _, err := io.WriteString(h, email) 58 grip.Warning(err) 59 return fmt.Sprintf("http://www.gravatar.com/avatar/%x?s=50", h.Sum(nil)) 60 }, 61 62 // DateFormat returns a time Formatted to the given layout and timezone. 63 // If the timezone is unset, it defaults to "New_York." 64 "DateFormat": func(when time.Time, layout string, timezone string) string { 65 if len(timezone) == 0 { 66 timezone = "America/New_York" // I ♥ NY 67 } 68 loc, err := time.LoadLocation(timezone) 69 if err != nil { 70 return when.Format(layout) 71 } 72 73 whenTZ := when.In(loc) 74 return whenTZ.Format(layout) 75 }, 76 77 // Static returns a link to a static file. 78 "Static": func(filetype, filename string) string { 79 return fmt.Sprintf("/static/%s/%s", filetype, filename) 80 }, 81 82 // RemoveANSI strips out ANSI color sequences in cases where it doesn't make sense to include 83 // them, e.g. raw task logs 84 "RemoveANSI": func(line string) string { 85 re, err := regexp.Compile("\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]") 86 if err != nil { 87 return "" 88 } 89 return re.ReplaceAllString(line, "") 90 }, 91 92 // Is Prod returns whether or not Evergreen is running in "production." 93 // Currently this is only used to toggle the use of minified css files. 94 "IsProd": func() bool { 95 return fo.IsProd 96 }, 97 98 // GetTimezone returns the timezone for a user. 99 // Defaults to "New_York". 100 "GetTimezone": func(u *user.DBUser) string { 101 if u != nil && u.Settings.Timezone != "" { 102 return u.Settings.Timezone 103 } 104 return "America/New_York" 105 }, 106 107 // MutableVar creates an unset MutableVar. 108 "MutableVar": func() interface{} { 109 return &MutableVar{""} 110 }, 111 112 // Trunc cuts off a string to be n characters long. 113 "Trunc": func(s string, n int) string { 114 if n > len(s) { 115 return s 116 } 117 return s[0:n] 118 }, 119 120 // UrlFor generates a URL for the given route. 121 "UrlFor": func(name string, pairs ...interface{}) (*url.URL, error) { 122 size := len(pairs) 123 strPairs := make([]string, size) 124 for i := 0; i < size; i++ { 125 if v, ok := pairs[i].(string); ok { 126 strPairs[i] = v 127 } else { 128 strPairs[i] = fmt.Sprint(pairs[i]) 129 } 130 } 131 132 route := fo.Router.Get(name) 133 if route == nil { 134 return nil, errors.Errorf("UrlFor: can't find a route named %v", name) 135 } 136 137 return route.URL(strPairs...) 138 }, 139 140 // HelpUrl returns the address of the Evergreen help page, 141 // if one is set. 142 "HelpUrl": func() string { 143 if fo.HelpHome != "" { 144 return fo.HelpHome 145 } 146 return defaultHelpURL 147 }, 148 } 149 150 staticsMD5, err := DirectoryChecksum(fo.WebHome) 151 if err != nil { 152 return nil, err 153 } 154 155 r["StaticsMD5"] = func() string { 156 return staticsMD5 157 } 158 return r, nil 159 160 }