github.com/elves/elvish@v0.15.0/website/cmd/genblog/render.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "text/template" 8 "time" 9 ) 10 11 // This file contains functions and types for rendering the blog. 12 13 // baseDot is the base for all "dot" structures used as the environment of the 14 // HTML template. 15 type baseDot struct { 16 BlogTitle string 17 Author string 18 RootURL string 19 HomepageTitle string 20 Categories []categoryMeta 21 22 CategoryMap map[string]string 23 BaseCSS string 24 } 25 26 func newBaseDot(bc *blogConf, css string) *baseDot { 27 b := &baseDot{bc.Title, bc.Author, bc.RootURL, 28 bc.Index.Title, bc.Categories, make(map[string]string), css} 29 for _, m := range bc.Categories { 30 b.CategoryMap[m.Name] = m.Title 31 } 32 return b 33 } 34 35 type articleDot struct { 36 *baseDot 37 article 38 } 39 40 type categoryDot struct { 41 *baseDot 42 Category string 43 Prelude string 44 Articles []articleMeta 45 ExtraCSS string 46 ExtraJS string 47 } 48 49 type feedDot struct { 50 *baseDot 51 Articles []article 52 LastModified rfc3339Time 53 } 54 55 // rfc3339Time wraps time.Time to provide a RFC3339 String() method. 56 type rfc3339Time time.Time 57 58 func (t rfc3339Time) String() string { 59 return time.Time(t).Format(time.RFC3339) 60 } 61 62 // contentIs generates a code snippet to fix the free reference "content" in 63 // the HTML template. 64 func contentIs(what string) string { 65 return fmt.Sprintf( 66 `{{ define "content" }} {{ template "%s-content" . }} {{ end }}`, 67 what) 68 } 69 70 func newTemplate(name, root string, sources ...string) *template.Template { 71 t := template.New(name).Funcs(template.FuncMap(map[string]interface{}{ 72 "is": func(s string) bool { return s == name }, 73 "rootURL": func() string { return root }, 74 })) 75 for _, source := range sources { 76 template.Must(t.Parse(source)) 77 } 78 return t 79 } 80 81 func openForWrite(fname string) *os.File { 82 file, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) 83 if err != nil { 84 log.Fatal(err) 85 } 86 return file 87 } 88 89 func executeToFile(t *template.Template, data interface{}, fname string) { 90 file := openForWrite(fname) 91 defer file.Close() 92 err := t.Execute(file, data) 93 if err != nil { 94 log.Fatalf("rendering %q: %s", fname, err) 95 } 96 }