template.go (view raw)
1//
2// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
3//
4// Permission to use, copy, modify, and distribute this software for any
5// purpose with or without fee is hereby granted, provided that the above
6// copyright notice and this permission notice appear in all copies.
7//
8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16package main
17
18import (
19 "errors"
20 "html/template"
21 "io"
22 "log"
23)
24
25type Template struct {
26 names []string
27 templates *template.Template
28 reload bool
29}
30
31func mapmaker(values ...interface{}) (map[string]interface{}, error) {
32 if len(values)%2 != 0 {
33 return nil, errors.New("need arguments in pairs")
34 }
35 dict := make(map[string]interface{}, len(values)/2)
36 for i := 0; i < len(values); i += 2 {
37 key, ok := values[i].(string)
38 if !ok {
39 return nil, errors.New("key must be string")
40 }
41 dict[key] = values[i+1]
42 }
43 return dict, nil
44}
45
46func loadtemplates(filenames ...string) (*template.Template, error) {
47 templates := template.New("")
48 templates.Funcs(template.FuncMap{
49 "map": mapmaker,
50 })
51 templates, err := templates.ParseFiles(filenames...)
52 if err != nil {
53 return nil, err
54 }
55 return templates, nil
56}
57
58func (t *Template) ExecuteTemplate(w io.Writer, name string, data interface{}) error {
59 if t.reload {
60 templates, err := loadtemplates(t.names...)
61 if err != nil {
62 return err
63 }
64 return templates.ExecuteTemplate(w, name, data)
65 }
66 return t.templates.ExecuteTemplate(w, name, data)
67}
68
69func ParseTemplates(reload bool, filenames ...string) *Template {
70 t := new(Template)
71 t.names = filenames
72 t.reload = reload
73 templates, err := loadtemplates(filenames...)
74 if err != nil {
75 log.Panic(err)
76 }
77 if !reload {
78 t.templates = templates
79 }
80 return t
81}