package main import ( "fmt" htemplate "html/template" "os" "path" "strings" "text/template" "github.com/pelletier/go-toml" ) // Config contains site configuration. type Config struct { Title string `toml:"title"` URLs []string `toml:"urls"` Tasks []*Task `toml:"tasks"` Feeds map[string]string `toml:"feeds"` Permalinks map[string]string `toml:"permalinks"` permalinks map[string]*template.Template templates *Templates } // Task represents a site build task. type Task struct { Input []string `toml:"input"` // input file suffixes OutputExt string `toml:"output"` // output file suffix TemplateExt string `toml:"template"` // template file suffix Preprocess map[string]string `toml:"preprocess"` // preprocess commands Postprocess string `toml:"postprocess"` // postprocess command StaticDir string `toml:"static_dir"` // static file directory OutputDir string `toml:"output_dir"` // output directory UglyURLs bool `toml:"ugly_urls"` // whether to use ugly URLs } func (t *Task) Match(ext string) bool { for i := range t.Input { if t.Input[i] == ext { return true } } return false } // LoadConfig loads the configuration from the provided path. func LoadConfig(path string) (*Config, error) { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() c := &Config{} if err := toml.NewDecoder(f).Decode(c); err != nil { return nil, err } // Parse permalinks c.permalinks = map[string]*template.Template{} for s := range c.Permalinks { t := template.New(fmt.Sprintf("permalink %q", s)).Funcs(funcs) _, err := t.Parse(c.Permalinks[s]) if err != nil { return nil, err } c.permalinks[s] = t } // Site contains site metadata passed to templates type Site struct { Title string URLs []string } funcs["site"] = func() Site { return Site{ Title: c.Title, URLs: c.URLs, } } funcs["partial"] = func(name string, data interface{}) (interface{}, error) { t, ok := c.templates.FindPartial(name) if !ok { return "", fmt.Errorf("Error: partial %q not found", name) } var b strings.Builder if err := t.Execute(&b, data); err != nil { return "", err } return b.String(), nil } // Initialize templates c.templates = NewTemplates() c.templates.Funcs(funcs) return c, nil } var funcs = map[string]interface{}{ "path": func() _path { return _path{} }, "strings": func() _strings { return _strings{} }, "safeHTML": func(s string) htemplate.HTML { return htemplate.HTML(s) }, "safeHTMLAttr": func(s string) htemplate.HTMLAttr { return htemplate.HTMLAttr(s) }, "safeCSS": func(s string) htemplate.CSS { return htemplate.CSS(s) }, "safeJS": func(s string) htemplate.JS { return htemplate.JS(s) }, "safeURL": func(s string) htemplate.URL { return htemplate.URL(s) }, } type _path struct{} func (_path) Base(s string) string { return path.Base(s) } func (_path) Clean(s string) string { return path.Clean(s) } func (_path) Dir(s string) string { return path.Dir(s) } func (_path) Ext(s string) string { return path.Ext(s) } func (_path) Join(elem ...string) string { return path.Join(elem...) } func (_path) Split(s string) (string, string) { return path.Split(s) } type _strings struct{} func (_strings) Count(a, b string) int { return strings.Count(a, b) } func (_strings) HasPrefix(a, b string) bool { return strings.HasPrefix(a, b) } func (_strings) HasSuffix(a, b string) bool { return strings.HasSuffix(a, b) } func (_strings) Join(elems []string, s string) string { return strings.Join(elems, s) } func (_strings) Repeat(s string, i int) string { return strings.Repeat(s, i) } func (_strings) Replace(a, b, c string, n int) string { return strings.Replace(a, b, c, n) } func (_strings) ReplaceAll(a, b, c string) string { return strings.ReplaceAll(a, b, c) } func (_strings) Split(a, b string) []string { return strings.Split(a, b) } func (_strings) Title(s string) string { return strings.Title(s) } func (_strings) ToLower(s string) string { return strings.ToLower(s) } func (_strings) ToUpper(s string) string { return strings.ToUpper(s) } func (_strings) Trim(a, b string) string { return strings.Trim(a, b) } func (_strings) TrimLeft(a, b string) string { return strings.TrimLeft(a, b) } func (_strings) TrimPrefix(a, b string) string { return strings.TrimPrefix(a, b) } func (_strings) TrimRight(a, b string) string { return strings.TrimRight(a, b) } func (_strings) TrimSpace(s string) string { return strings.TrimSpace(s) } func (_strings) TrimSuffix(a, b string) string { return strings.TrimSuffix(a, b) }