package main import ( "fmt" "log" "os" "path" "strings" "text/template" "github.com/pelletier/go-toml" ) // Site represents a site. type Site struct { Title string `toml:"title"` URLs []string `toml:"urls"` Tasks []*Task `toml:"tasks"` Feeds map[string]string `toml:"feeds"` Params map[string]string `toml:"params"` Permalinks map[string]string `toml:"permalinks"` permalinks map[string]*template.Template templates Templates root *Dir } // 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 Feeds []Feed `toml:"feeds"` feeds map[string][]Feed } type Feed struct { InputDir string `toml:"input_dir"` Title string `toml:"title"` Template string `toml:"template"` Output string `toml:"output"` } func (t *Task) Match(ext string) bool { for i := range t.Input { if t.Input[i] == ext { return true } } return false } // LoadSite loads the site with the given configuration file. func LoadSite(config string) (*Site, error) { f, err := os.Open(config) if err != nil { return nil, err } defer f.Close() site := &Site{} if err := toml.NewDecoder(f).Decode(site); err != nil { return nil, err } funcs := site.funcs() // Parse permalinks site.permalinks = map[string]*template.Template{} for path := range site.Permalinks { t := template.New(fmt.Sprintf("permalink %q", path)).Funcs(funcs) _, err := t.Parse(site.Permalinks[path]) if err != nil { return nil, err } site.permalinks[path] = t } // Load templates templateExts := []string{} for _, task := range site.Tasks { if task.TemplateExt != "" { templateExts = append(templateExts, task.TemplateExt) } } site.templates.Funcs(funcs) if err := site.templates.Load("templates", templateExts); err != nil { return nil, err } // Populate task feeds map for _, task := range site.Tasks { task.feeds = map[string][]Feed{} for _, feed := range task.Feeds { task.feeds[feed.InputDir] = append(task.feeds[feed.InputDir], feed) } } // deprecate [feeds] if len(site.Feeds) > 0 { log.Println("The [feeds] configuration is deprecated") for _, task := range site.Tasks { if len(task.Feeds) > 0 { log.Println("and can't be used along [[tasks.feeds]]") return nil, fmt.Errorf("please remove (or rename) the [feeds] category") } } log.Println("Please replace it with [[tasks.feeds]] in every task needing feeds:") for permalink, title := range site.Feeds { dir := strings.Trim(permalink, "/") output := path.Join(dir, "atom.xml") fmt.Fprintf(log.Writer(), `[[tasks.feeds]] input_dir = %q title = %q template = "atom.xml" output = %q `, dir, title, output) } log.Println("You will also need to change .Entries to .Pages in \"atom.xml\"") } return site, nil } func (s *Site) dir(path string) *Dir { return s.root.getDir(path) } func (s *Site) page(path string) *Page { return s.root.getPage(path) }