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  }