func NewTemplate() *template.Template { return template.New("").Funcs(template.FuncMap(map[string]interface{}{ "q": func(fieldName string) (interface{}, error) { return nil, errors.New("The q template dummy function was called") }, })) }
func TestTemplateFuncMap_join(t *testing.T) { app := kocha.NewTestApp() funcMap := template.FuncMap(app.Template.FuncMap) tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(`{{join .Arr .Sep}}`)) var buf bytes.Buffer for _, v := range []struct { Arr interface{} Sep string expect string }{ {[]int{1, 2, 3}, "&", "1&2&3"}, {[2]uint{12, 34}, " and ", "12 and 34"}, {[]string{"alice", "bob", "carol"}, ", ", "alice, bob, carol"}, {[]string(nil), "|", ""}, {[]bool{}, " or ", ""}, {[]interface{}{"1", 2, "three", uint32(4)}, "-", "1-2-three-4"}, {[]string{"あ", "い", "う", "え", "お"}, "_", "あ_い_う_え_お"}, {[]string{"a", "b", "c"}, "∧", "a∧b∧c"}, } { buf.Reset() if err := tmpl.Execute(&buf, v); err != nil { t.Error(err) continue } actual := buf.String() expect := v.expect if !reflect.DeepEqual(actual, expect) { t.Errorf(`{{join %#v %#v}} => %#v; want %#v`, v.Arr, v.Sep, actual, expect) } } }
func TestTemplate_FuncMap_url(t *testing.T) { app := kocha.NewTestApp() funcMap := template.FuncMap(app.Template.FuncMap) func() { tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(`{{url "root"}}`)) var buf bytes.Buffer if err := tmpl.Execute(&buf, nil); err != nil { panic(err) } actual := buf.String() expected := "/" if !reflect.DeepEqual(actual, expected) { t.Errorf("Expect %q, but %q", expected, actual) } }() func() { tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(`{{url "user" 713}}`)) var buf bytes.Buffer if err := tmpl.Execute(&buf, nil); err != nil { panic(err) } actual := buf.String() expected := "/user/713" if !reflect.DeepEqual(actual, expected) { t.Errorf("Expect %v, but %v", expected, actual) } }() }
// TemplatesFuncs adds functions that will be available to all templates. // It is legal to overwrite elements of the map. func TemplatesFuncs(funcs FuncMap) { if templates == nil { panic(errNoTemplatesDir) } templates.Funcs(template.FuncMap(funcs)) }
func TestTemplateFuncMap_flash(t *testing.T) { c := newTestContext("testctrlr", "") funcMap := template.FuncMap(c.App.Template.FuncMap) for _, v := range []struct { key string expect string }{ {"", ""}, {"success", "test succeeded"}, {"success", "test successful"}, {"error", "test failed"}, {"error", "test failure"}, } { c.Flash = kocha.Flash{} c.Flash.Set(v.key, v.expect) tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(fmt.Sprintf(`{{flash . "unknown"}}{{flash . "%s"}}`, v.key))) var buf bytes.Buffer if err := tmpl.Execute(&buf, c); err != nil { t.Error(err) continue } actual := buf.String() expect := v.expect if !reflect.DeepEqual(actual, expect) { t.Errorf(`{{flash . %#v}} => %#v; want %#v`, v.key, actual, expect) } } }
func BenchmarkBigGo(b *testing.B) { b.ReportAllocs() tmpl := template.New("") tmpl.Funcs(template.FuncMap{"t": func(s string) string { return s }}) tmpl.Funcs(template.FuncMap(templateFuncs.asTemplateFuncMap())) readFile := func(name string) string { data, err := ioutil.ReadFile(filepath.Join("_testdata", name)) if err != nil { b.Fatal(err) } return "{{ $Vars := .Vars }}\n" + string(data) } if _, err := tmpl.Parse(readFile("1.html")); err != nil { b.Fatal(err) } t2 := tmpl.New("2.html") if _, err := t2.Parse(readFile("2.html")); err != nil { b.Fatal(err) } var buf bytes.Buffer if err := tmpl.Execute(&buf, nil); err != nil { b.Fatal(err) } buf.Reset() b.ResetTimer() for ii := 0; ii < b.N; ii++ { tmpl.Execute(&buf, nil) buf.Reset() } }
func TestTemplate_FuncMap_in(t *testing.T) { app := kocha.NewTestApp() funcMap := template.FuncMap(app.Template.FuncMap) var buf bytes.Buffer for _, v := range []struct { Arr interface{} Sep interface{} expect string err error }{ {[]string{"b", "a", "c"}, "a", "true", nil}, {[]string{"ab", "b", "c"}, "a", "false", nil}, {nil, "a", "", fmt.Errorf("valid types are slice, array and string, got `invalid'")}, } { buf.Reset() tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(`{{in .Arr .Sep}}`)) err := tmpl.Execute(&buf, v) if !strings.HasSuffix(fmt.Sprint(err), fmt.Sprint(v.err)) { t.Errorf(`{{in %#v %#v}}; error has "%v"; want "%v"`, v.Arr, v.Sep, err, v.err) } actual := buf.String() expect := v.expect if !reflect.DeepEqual(actual, expect) { t.Errorf(`{{in %#v %#v}} => %#v; want %#v`, v.Arr, v.Sep, actual, expect) } } }
// Creates HTML template with predefined functions func NewHtml(name string) *template.Template { tmpl := template.New(name) extends := template.FuncMap(map[string]interface{}{ "extends": func(name string, data interface{}) (html template.HTML, err error) { buf := bytes.NewBuffer([]byte{}) if err = tmpl.ExecuteTemplate(buf, name, data); err == nil { html = template.HTML(buf.String()) } return }, }) return tmpl.Funcs(template.FuncMap(coreFuncs)).Funcs(extends) }
func NewConf(name string, backends conf.EnabledBackends, text string) (c *Conf, err error) { defer errRecover(&err) c = &Conf{ Name: name, Vars: make(map[string]string), Templates: make(map[string]*conf.Template), Alerts: make(map[string]*conf.Alert), Notifications: make(map[string]*conf.Notification), RawText: text, bodies: htemplate.New(name).Funcs(htemplate.FuncMap(defaultFuncs)), subjects: ttemplate.New(name).Funcs(defaultFuncs), Lookups: make(map[string]*conf.Lookup), Macros: make(map[string]*conf.Macro), writeLock: make(chan bool, 1), deferredSections: make(map[string][]deferredSection), backends: backends, } c.tree, err = parse.Parse(name, text) if err != nil { c.error(err) } saw := make(map[string]bool) for _, n := range c.tree.Root.Nodes { c.at(n) switch n := n.(type) { case *parse.PairNode: c.seen(n.Key.Text, saw) c.loadGlobal(n) case *parse.SectionNode: c.loadSection(n) default: c.errorf("unexpected parse node %s", n) } } loadSections := func(sectionType string) { for _, dSec := range c.deferredSections[sectionType] { c.at(dSec.SectionNode) dSec.LoadFunc(dSec.SectionNode) } } loadSections("template") if c.unknownTemplate != "" { t, ok := c.Templates[c.unknownTemplate] if !ok { c.errorf("template not found: %s", c.unknownTemplate) } c.UnknownTemplate = t } loadSections("notification") loadSections("macro") loadSections("lookup") loadSections("alert") c.genHash() return }
func (c *Conf) loadTemplate(s *parse.SectionNode) { name := s.Name.Text if _, ok := c.Templates[name]; ok { c.errorf("duplicate template name: %s", name) } t := conf.Template{ Vars: make(map[string]string), Name: name, } t.Text = s.RawText t.Locator = newSectionLocator(s) funcs := ttemplate.FuncMap{ "V": func(v string) string { return c.Expand(v, t.Vars, false) }, } saw := make(map[string]bool) for _, p := range s.Nodes.Nodes { c.at(p) switch p := p.(type) { case *parse.PairNode: c.seen(p.Key.Text, saw) v := p.Val.Text switch k := p.Key.Text; k { case "body": t.RawBody = v tmpl := c.bodies.New(name).Funcs(htemplate.FuncMap(funcs)) _, err := tmpl.Parse(t.RawBody) if err != nil { c.error(err) } t.Body = tmpl case "subject": t.RawSubject = v tmpl := c.subjects.New(name).Funcs(funcs) _, err := tmpl.Parse(t.RawSubject) if err != nil { c.error(err) } t.Subject = tmpl default: if !strings.HasPrefix(k, "$") { c.errorf("unknown key %s", k) } t.Vars[k] = v t.Vars[k[1:]] = t.Vars[k] } default: c.errorf("unexpected node") } } c.at(s) if t.Body == nil && t.Subject == nil { c.errorf("neither body or subject specified") } c.Templates[name] = &t }
func TestTemplate_FuncMap_in_withInvalidType(t *testing.T) { app := kocha.NewTestApp() funcMap := template.FuncMap(app.Template.FuncMap) tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(`{{in 1 1}}`)) var buf bytes.Buffer if err := tmpl.Execute(&buf, nil); err == nil { t.Errorf("Expect errors, but no errors") } }
func MakeMixer(tpdir string, fMap map[string]interface{}) func(...string) *template.Template { return func(fileNames ...string) *template.Template { names := make([]string, len(fileNames)) for i, val := range fileNames { names[i] = tpdir + val + ".html" } return template.Must(template.New("").Funcs(template.FuncMap(fMap)).ParseFiles(names...)) } }
func New(name, text string) (c *Conf, err error) { defer errRecover(&err) c = &Conf{ Name: name, CheckFrequency: time.Minute * 5, DefaultRunEvery: 1, HTTPListen: ":8070", StateFile: "bosun.state", LedisDir: "ledis_data", LedisBindAddr: "127.0.0.1:9565", MinGroupSize: 5, PingDuration: time.Hour * 24, ResponseLimit: 1 << 20, // 1MB SearchSince: opentsdb.Day * 3, TSDBVersion: &opentsdb.Version2_1, UnknownThreshold: 5, Vars: make(map[string]string), Templates: make(map[string]*Template), Alerts: make(map[string]*Alert), Notifications: make(map[string]*Notification), RawText: text, bodies: htemplate.New(name).Funcs(htemplate.FuncMap(defaultFuncs)), subjects: ttemplate.New(name).Funcs(defaultFuncs), Lookups: make(map[string]*Lookup), Macros: make(map[string]*Macro), } c.tree, err = parse.Parse(name, text) if err != nil { c.error(err) } saw := make(map[string]bool) for _, n := range c.tree.Root.Nodes { c.at(n) switch n := n.(type) { case *parse.PairNode: c.seen(n.Key.Text, saw) c.loadGlobal(n) case *parse.SectionNode: c.loadSection(n) default: c.errorf("unexpected parse node %s", n) } } if c.Hostname == "" { c.Hostname = c.HTTPListen if strings.HasPrefix(c.Hostname, ":") { h, err := os.Hostname() if err != nil { c.at(nil) c.error(err) } c.Hostname = h + c.Hostname } } return }
// Loads localization, template functions and executes the template. func (d *Display) execute(wr io.Writer, fileContents string) error { loc, err := display_model.LoadLocTempl(d.ctx.FileSys(), fileContents, d.ctx.User().Languages()) // TODO: think about errors here. if err != nil { return err } vctx := d.ctx.ViewContext() vctx.Publish("loc", loc) funcMap := template.FuncMap(builtins(d.ctx)) t, err := template.New("tpl").Funcs(funcMap).Parse(fileContents) if err != nil { return err } return t.Execute(wr, vctx.Get()) // TODO: watch for errors in execution. }
func TestTemplate_FuncMap_nl2br(t *testing.T) { app := kocha.NewTestApp() funcMap := template.FuncMap(app.Template.FuncMap) tmpl := template.Must(template.New("test").Funcs(funcMap).Parse(`{{nl2br "a\nb\nc\n"}}`)) var buf bytes.Buffer if err := tmpl.Execute(&buf, nil); err != nil { panic(err) } actual := buf.String() expected := "a<br>b<br>c<br>" if !reflect.DeepEqual(actual, expected) { t.Errorf("Expect %q, but %q", expected, actual) } }
/** * 包含模板 directive */ func MyTemplateDirective(tname string, data interface{}) template.HTML { s, err := LoadHtmlTemplateToStr(tname) if err != nil { log.Println("解析模板[", tname, "]错误,", err.Error()) return template.HTML("") } t, err := template.New(tname).Funcs(template.FuncMap(PullFuncMap)).Parse(s) if err != nil { log.Println("解析模板[", tname, "]错误,", err.Error()) return template.HTML("") } buff := bytes.NewBufferString("") t.Execute(buff, data) return template.HTML(buff.String()) }
/** * 编译html为go模板 */ func ParseTemplate(tname string) (*template.Template, error) { tmpl_str, err := LoadHtmlTemplateToStr(tname) if err != nil { log.Println("加载模板失败,", err.Error()) return nil, err } //second compile html string //parse模版 t, err := template.New(tname).Funcs(template.FuncMap(PullFuncMap)).Parse(tmpl_str) if err != nil { log.Println("编译模板失败!", err.Error()) return nil, err } return t, nil }
func main() { settings := evergreen.GetSettingsOrExit() home := evergreen.FindEvergreenHome() uis, err := ui.New(settings, home) if err != nil { fmt.Println("Failed to create ui server: %v", err) os.Exit(1) } router, err := uis.NewRouter() if err != nil { fmt.Println("Failed to create router:", err) os.Exit(1) } webHome := filepath.Join(uis.Home, "public") functionOptions := ui.FuncOptions{webHome, uis.Settings.Ui.HelpUrl, true, router} functions, err := ui.MakeTemplateFuncs(functionOptions, uis.Settings.SuperUsers) htmlFunctions := htmlTemplate.FuncMap(functions) textFunctions := textTemplate.FuncMap(functions) if err != nil { fmt.Println("Failed to create template function map:", err) os.Exit(1) } uis.Render = render.New(render.Options{ Directory: filepath.Join(uis.Home, ui.WebRootPath, ui.Templates), DisableCache: !uis.Settings.Ui.CacheTemplates, HtmlFuncs: htmlFunctions, TextFuncs: textFunctions, }) err = uis.InitPlugins() if err != nil { fmt.Println("WARNING: Error initializing plugins:", err) } n := negroni.New() n.Use(negroni.NewStatic(http.Dir(webHome))) n.Use(ui.NewLogger()) n.Use(negroni.HandlerFunc(ui.UserMiddleware(uis.UserManager))) n.UseHandler(router) graceful.Run(uis.Settings.Ui.HttpListenAddr, requestTimeout, n) evergreen.Logger.Logf(slogger.INFO, "UI server cleanly terminated") }
func (this *SunnyPublisher) Publish(wr io.Writer, name string, data interface{}) { // TODO: use sync.Pool instead once GAE supports 1.3 // get cloned template from pool // add contextual funcmap to the template if strings.HasSuffix(name, ".html") { ht, err := this.htmpl.Clone() ht.Funcs(htemplate.FuncMap(this.fmap)) if err == nil { ht = ht.Lookup(name) if ht != nil { ht.Execute(wr, data) } else { goto renderer } } else { goto renderer } } else { ht, err := this.tmpl.Clone() ht.Funcs(template.FuncMap(this.fmap)) if err == nil { if ht != nil { ht.Execute(wr, data) } else { goto renderer } } else { goto renderer } } return renderer: ext := ".html" b, err := this.renderer[ext](name, data) if err == nil { wr.Write(b) } }
func (t *Template) buildAppTemplateSet(buf *bytes.Buffer, l int, m map[templateKey]*template.Template, appName string, templates map[string]map[string]string) error { for ext, templateInfos := range templates { tmpl := template.New("") for name, path := range templateInfos { buf.Truncate(l) var body string if data := t.app.ResourceSet.Get(path); data != nil { if b, ok := data.(string); ok { buf.WriteString(b) body = buf.String() } } else { f, err := os.Open(path) if err != nil { return err } _, err = io.Copy(buf, f) f.Close() if err != nil { return err } body = buf.String() t.app.ResourceSet.Add(path, body) } if _, err := tmpl.New(name).Delims(t.LeftDelim, t.RightDelim).Funcs(template.FuncMap(t.FuncMap)).Parse(body); err != nil { return err } } for _, t := range tmpl.Templates() { key := templateKey{ appName: appName, name: strings.TrimSuffix(t.Name(), ext), format: ext[1:], // truncate the leading dot. } if strings.HasPrefix(key.name, layoutPath) { key.isLayout = true key.name = key.name[len(layoutPath):] } m[key] = t } } return nil }
// Parse is converts the input data into html. func (h *HTML) Parse(f []Field) string { t := defaultTemplate if h.Template != "" { // template check _, err := os.Stat(h.Template) if err == nil { t = template.Must(template.New(filepath.Base(h.Template)).Funcs(template.FuncMap(fns)).ParseFiles(h.Template)) } else { log.Warnf("template does not exist: %s, stat error: %v", h.Template, err) } } var buffer bytes.Buffer err := t.Execute(&buffer, map[string]interface{}{"fields": f}) if err != nil { log.Panicf("execute template error: %v", err) } return buffer.String() }
// Loads localization, template functions and executes the template. func prepareAndExec(uni *context.Uni, file string) { root := uni.Root host := uni.Req.Host dat := uni.Dat opt := uni.Opt w := uni.W langs, has := jsonp.Get(dat, "_user.languages") // _user should always has languages field if !has { langs = []string{"en"} } langs_s := toStringSlice(langs) if !has { langs = []string{"en"} } loc, _ := display_model.LoadLocTempl(file, langs_s, root, scut.GetTPath(opt, host), nil) // TODO: think about errors here. dat["loc"] = merge(dat["loc"], loc) funcMap := template.FuncMap(builtins(uni)) t, _ := template.New("tpl").Funcs(funcMap).Parse(string(file)) w.Header().Set("Content-Type", "text/html; charset=utf-8") t.Execute(w, dat) // TODO: watch for errors in execution. }
// FromGlobs calls ParseGlob on all path globs provided and returns the // resulting Template. func FromGlobs(paths ...string) (*Template, error) { t := &Template{ text: tmpltext.New("").Option("missingkey=zero"), html: tmplhtml.New("").Option("missingkey=zero"), } var err error t.text = t.text.Funcs(tmpltext.FuncMap(DefaultFuncs)) t.html = t.html.Funcs(tmplhtml.FuncMap(DefaultFuncs)) b, err := deftmpl.Asset("template/default.tmpl") if err != nil { return nil, err } if t.text, err = t.text.Parse(string(b)); err != nil { return nil, err } if t.html, err = t.html.Parse(string(b)); err != nil { return nil, err } for _, tp := range paths { // ParseGlob in the template packages errors if not at least one file is // matched. We want to allow empty matches that may be populated later on. p, err := filepath.Glob(tp) if err != nil { return nil, err } if len(p) > 0 { if t.text, err = t.text.ParseGlob(tp); err != nil { return nil, err } if t.html, err = t.html.ParseGlob(tp); err != nil { return nil, err } } } return t, nil }
//newHtemplate adds funcmap to template var and parse files. func newHtemplate(templateDir string) *Htemplate { t := &Htemplate{htmlTemplate.New("")} t.Funcs(htmlTemplate.FuncMap(funcMap)) templateFiles := filepath.Join(templateDir, "*.txt") if util.IsDir(templateDir) { _, err := t.ParseGlob(templateFiles) if err != nil { log.Fatal(err) } } mat, err := filepath.Glob(templateFiles) if err != nil { log.Fatal(err) } e := make(map[string]struct{}) for _, m := range mat { e[filepath.Base(m)] = struct{}{} } dir, err := util.AssetDir("gou_template") if err != nil { log.Fatal(err) } for _, a := range dir { if _, exist := e[path.Base(a)]; exist { continue } c, err := util.Asset(path.Join("gou_template", a)) if err != nil { log.Fatal(err) } if _, err := t.Parse(string(c)); err != nil { log.Fatal(err) } } return t }
func (r *HTMLTemplateRenderer) Render(name string, vars librenderer.M) ([]byte, error) { if r.memcache == nil { r.memcache = make(map[string]*template.Template) } if r.memlock == nil { r.memlock = new(sync.Mutex) } r.memlock.Lock() defer r.memlock.Unlock() tpl, exists := r.memcache[name] if !exists { src, err := r.Assets.Asset(name) if err != nil { return []byte{}, err } tpl, err = template.New(name).Parse(string(src)) if err != nil { return []byte{}, err } if r.Funcs != nil { tpl = tpl.Funcs(template.FuncMap(r.Funcs)) } r.memcache[name] = tpl } b := new(bytes.Buffer) if err := tpl.Execute(b, vars); err != nil { return []byte{}, err } return b.Bytes(), nil }
func benchmarkHTMLTemplate(b *testing.B, tests []*templateTest) { b.ReportAllocs() templates := make([]*template.Template, len(tests)) for ii, v := range tests { tmpl := template.New("template.html") tmpl.Funcs(template.FuncMap(templateFuncs.asTemplateFuncMap())) _, err := tmpl.Parse(v.tmpl) if err != nil { b.Fatalf("can't parse %q: %s", v.tmpl, err) } // Execute once to add the escaping hooks tmpl.Execute(ioutil.Discard, nil) templates[ii] = tmpl } var buf bytes.Buffer b.ResetTimer() for ii := 0; ii < b.N; ii++ { for ii, v := range templates { v.Execute(&buf, tests[ii].data) } buf.Reset() } }
// ExpandHTML expands a template with HTML escaping, with templates read from the given files. func (te Expander) ExpandHTML(templateFiles []string) (result string, resultErr error) { defer func() { if r := recover(); r != nil { var ok bool resultErr, ok = r.(error) if !ok { resultErr = fmt.Errorf("panic expanding template %v: %v", te.name, r) } } }() tmpl := html_template.New(te.name).Funcs(html_template.FuncMap(te.funcMap)) tmpl.Option("missingkey=zero") tmpl.Funcs(html_template.FuncMap{ "tmpl": func(name string, data interface{}) (html_template.HTML, error) { var buffer bytes.Buffer err := tmpl.ExecuteTemplate(&buffer, name, data) return html_template.HTML(buffer.String()), err }, }) tmpl, err := tmpl.Parse(te.text) if err != nil { return "", fmt.Errorf("error parsing template %v: %v", te.name, err) } if len(templateFiles) > 0 { _, err = tmpl.ParseFiles(templateFiles...) if err != nil { return "", fmt.Errorf("error parsing template files for %v: %v", te.name, err) } } var buffer bytes.Buffer err = tmpl.Execute(&buffer, te.data) if err != nil { return "", fmt.Errorf("error executing template %v: %v", te.name, err) } return buffer.String(), nil }
func (t *Templates) ParseDir(dir, prefix string, funcMap FuncMap) { filepath.Walk(dir, func(p string, i os.FileInfo, e error) error { if i == nil || i.IsDir() { return nil } if strings.HasSuffix(p, ".tmpl.html") || !strings.HasSuffix(p, ".html") { return nil } rel, err := filepath.Rel(dir, p) if err != nil { return err } r, err := t.processTemplate(dir, rel) if err != nil { panic(err) } b := &bytes.Buffer{} if _, err = b.ReadFrom(r); err != nil { panic(err) } n := prefix + filepath.ToSlash(rel) t.m[n] = template.New(``).Funcs(template.FuncMap(funcMap)) template.Must(t.m[n].Parse(b.String())) if _, err = os.Stat(path.Join(dir, rel[:len(rel)-5], "index.html")); os.IsNotExist(err) { t.m[n[:len(n)-5]] = t.m[n] } if len(rel) >= 10 && rel[len(rel)-10:] == "index.html" { t.m[strings.TrimRight(n[:len(n)-10], "/")] = t.m[n] } return nil }) }
func main() { settings := evergreen.GetSettingsOrExit() if settings.Ui.LogFile != "" { evergreen.SetLogger(settings.Ui.LogFile) } db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(settings)) home := evergreen.FindEvergreenHome() userManager, err := auth.LoadUserManager(settings.AuthConfig) if err != nil { fmt.Println("Failed to create user manager:", err) os.Exit(1) } cookieStore := sessions.NewCookieStore([]byte(settings.Ui.Secret)) uis := ui.UIServer{ nil, // render settings.Ui.Url, // RootURL userManager, // User Manager *settings, // mci settings cookieStore, // cookiestore nil, // plugin panel manager } router, err := uis.NewRouter() if err != nil { fmt.Println("Failed to create router:", err) os.Exit(1) } webHome := filepath.Join(home, "public") functionOptions := ui.FuncOptions{webHome, settings.Ui.HelpUrl, true, router} functions, err := ui.MakeTemplateFuncs(functionOptions, settings.SuperUsers) htmlFunctions := htmlTemplate.FuncMap(functions) textFunctions := textTemplate.FuncMap(functions) if err != nil { fmt.Println("Failed to create template function map:", err) os.Exit(1) } uis.Render = render.New(render.Options{ Directory: filepath.Join(home, ui.WebRootPath, ui.Templates), DisableCache: !settings.Ui.CacheTemplates, HtmlFuncs: htmlFunctions, TextFuncs: textFunctions, }) err = uis.InitPlugins() if err != nil { fmt.Println("WARNING: Error initializing plugins:", err) } n := negroni.New() n.Use(negroni.NewStatic(http.Dir(webHome))) n.Use(ui.NewLogger()) n.Use(negroni.HandlerFunc(ui.UserMiddleware(userManager))) n.UseHandler(router) graceful.Run(settings.Ui.HttpListenAddr, requestTimeout, n) evergreen.Logger.Logf(slogger.INFO, "UI server cleanly terminated") }
var htmlFuncs = template.FuncMap(map[string]interface{}{ "pct": pct, "lastRev": func(classes []*failureClass) *Revision { // TODO: Ugh. It's lame that the same Revs is in every // failureClass. revs := classes[0].Revs return revs[len(revs)-1] }, "numCommits": func(r FlakeRegion) int { return r.Last - r.First + 1 }, "groupByT": func(failures []*failure) map[int][]*failure { out := make(map[int][]*failure) if len(failures) == 0 { return out } lastI, lastT := 0, failures[0].T for i := 1; i < len(failures); i++ { if failures[i].T != lastT { out[lastT] = failures[lastI:i] lastI, lastT = i, failures[i].T } } out[lastT] = failures[lastI:] return out }, "slice": func(v interface{}, start, end int) interface{} { val := reflect.ValueOf(v) if start < 0 { start = val.Len() + start } if end < 0 { end = val.Len() + end } return val.Slice(start, end).Interface() }, })