ref: 8afff8c7c43d3e593313832dfa371461a0cb133b
parent: c0a046cbfb24d64847e6b8a5cd8be8a7e8a0fc80
author: spf13 <steve.francia@gmail.com>
date: Thu Apr 10 04:10:12 EDT 2014
Preliminary Theme Support
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -49,7 +49,7 @@
var hugoCmdV *cobra.Command
var BuildWatch, Draft, UglyUrls, Verbose, Logging, VerboseLog, DisableRSS bool
-var Source, Destination, BaseUrl, CfgFile, LogFile string
+var Source, Destination, Theme, BaseUrl, CfgFile, LogFile string
func Execute() {AddCommands()
@@ -68,6 +68,7 @@
HugoCmd.PersistentFlags().BoolVar(&DisableRSS, "disableRSS", false, "Do not build RSS files")
HugoCmd.PersistentFlags().StringVarP(&Source, "source", "s", "", "filesystem path to read files relative from")
HugoCmd.PersistentFlags().StringVarP(&Destination, "destination", "d", "", "filesystem path to write files to")
+ HugoCmd.PersistentFlags().StringVarP(&Theme, "theme", "t", "", "theme to use (located in /themes/THEMENAME/)")
HugoCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
HugoCmd.PersistentFlags().BoolVar(&UglyUrls, "uglyurls", false, "if true, use /filename.html instead of /filename/")
HugoCmd.PersistentFlags().StringVarP(&BaseUrl, "base-url", "b", "", "hostname (and path) to the root eg. http://spf13.com/")
@@ -126,6 +127,11 @@
}
viper.Set("BaseUrl", BaseUrl)}
+
+ if Theme != "" {+ viper.Set("theme", Theme)+ }
+
if Destination != "" { viper.Set("PublishDir", Destination)}
@@ -176,10 +182,24 @@
func copyStatic() error { staticDir := helpers.AbsPathify(viper.GetString("StaticDir")) + "/" if _, err := os.Stat(staticDir); os.IsNotExist(err) {+ jww.ERROR.Println("Unable to find Static Directory:", viper.GetString("theme"), "in", staticDir)return nil
}
publishDir := helpers.AbsPathify(viper.GetString("PublishDir")) + "/"+
+ if themeSet() {+ themeDir := helpers.AbsPathify("themes/"+viper.GetString("theme")) + "/static/"+ if _, err := os.Stat(themeDir); os.IsNotExist(err) {+ jww.ERROR.Println("Unable to find static directory for theme :", viper.GetString("theme"), "in", themeDir)+ return nil
+ }
+
+ // Copy Static to Destination
+ jww.INFO.Println("syncing from", themeDir, "to", publishDir)+ return fsync.Sync(publishDir, themeDir)
+ }
+
// Copy Static to Destination
jww.INFO.Println("syncing from", staticDir, "to", publishDir)return fsync.Sync(publishDir, staticDir)
@@ -202,8 +222,15 @@
filepath.Walk(helpers.AbsPathify(viper.GetString("ContentDir")), walker) filepath.Walk(helpers.AbsPathify(viper.GetString("LayoutDir")), walker) filepath.Walk(helpers.AbsPathify(viper.GetString("StaticDir")), walker)+ if themeSet() {+ filepath.Walk(helpers.AbsPathify("themes/"+viper.GetString("theme")), walker)+ }
return a
+}
+
+func themeSet() bool {+ return viper.GetString("theme") != ""}
func buildSite(watching ...bool) (err error) {--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -1,4 +1,4 @@
-// Copyright © 2013 Steve Francia <spf@spf13.com>.
+// Copyright © 2013-14 Steve Francia <spf@spf13.com>.
//
// Licensed under the Simple Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -132,6 +132,9 @@
func (s *Site) prepTemplates() {s.Tmpl = bundle.NewTemplate()
s.Tmpl.LoadTemplates(s.absLayoutDir())
+ if s.hasTheme() {+ s.Tmpl.LoadTemplatesWithPrefix(s.absThemeDir()+"/layouts", "theme")
+ }
}
func (s *Site) addTemplate(name, data string) error {@@ -244,6 +247,14 @@
}
}
+func (s *Site) hasTheme() bool {+ return viper.GetString("theme") != ""+}
+
+func (s *Site) absThemeDir() string {+ return helpers.AbsPathify("themes/" + viper.GetString("theme"))+}
+
func (s *Site) absLayoutDir() string { return helpers.AbsPathify(viper.GetString("LayoutDir"))}
@@ -422,7 +433,7 @@
layouts = append(layouts, "_default/single.html")
}
- return s.render(p, p.TargetPath(), layouts...)
+ return s.render(p, p.TargetPath(), s.appendThemeTemplates(layouts)...)
}(page)
}
wg.Wait()
@@ -433,6 +444,34 @@
return nil
}
+func (s *Site) appendThemeTemplates(in []string) []string {+ if s.hasTheme() {+ out := []string{}+ // First place all non internal templates
+ for _, t := range in {+ if !strings.HasPrefix("_internal/", t) {+ out = append(out, t)
+ }
+ }
+
+ // Then place theme templates with the same names
+ for _, t := range in {+ if !strings.HasPrefix("_internal/", t) {+ out = append(out, "theme/"+t)
+ }
+ }
+ // Lastly place internal templates
+ for _, t := range in {+ if strings.HasPrefix("_internal/", t) {+ out = append(out, "theme/"+t)
+ }
+ }
+ return out
+ } else {+ return in
+ }
+}
+
// Render the listing pages based on the meta data
// each unique term within a taxonomy will have a page created
func (s *Site) RenderTaxonomiesLists() (err error) {@@ -451,8 +490,8 @@
n.Date = o[0].Page.Date
n.Data[singular] = o
n.Data["Pages"] = o.Pages()
- err = s.render(n, base+".html", "taxonomies/"+singular+".html", "indexes/"+singular+".html")
- //TODO add , "_default/taxonomy.html", "_default/list.html"
+ layouts := []string{"taxonomy/" + singular + ".html", "indexes/" + singular + ".html", "_default/taxonomy.html", "_default/list.html"}+ err = s.render(n, base+".html", s.appendThemeTemplates(layouts)...)
if err != nil {return err
}
@@ -460,7 +499,8 @@
if !viper.GetBool("DisableRSS") {// XML Feed
s.setUrls(n, base+".xml")
- err := s.render(n, base+".xml", "rss.xml", "_internal/_default/rss.xml")
+ rssLayouts := []string{"taxonomy/" + singular + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}+ err := s.render(n, base+".xml", s.appendThemeTemplates(rssLayouts)...)
if err != nil {return err
}
@@ -475,22 +515,20 @@
// Render a page per taxonomy that lists the terms for that taxonomy
func (s *Site) RenderListsOfTaxonomyTerms() (err error) {- layouts := []string{"taxonomies/termslist.html", "indexes/indexes.html"}- // TODO add "_default/termsList.html", "_default/termslist.html"
- // TODO add support for unique taxonomy terms list (`single`terms.html)
- if s.layoutExists(layouts...) {- taxonomies := viper.GetStringMapString("Taxonomies")- for singular, plural := range taxonomies {- n := s.NewNode()
- n.Title = strings.Title(plural)
- s.setUrls(n, plural)
- n.Data["Singular"] = singular
- n.Data["Plural"] = plural
- n.Data["Terms"] = s.Taxonomies[plural]
- // keep the following just for legacy reasons
- n.Data["OrderedIndex"] = n.Data["Terms"]
- n.Data["Index"] = n.Data["Terms"]
-
+ taxonomies := viper.GetStringMapString("Taxonomies")+ for singular, plural := range taxonomies {+ n := s.NewNode()
+ n.Title = strings.Title(plural)
+ s.setUrls(n, plural)
+ n.Data["Singular"] = singular
+ n.Data["Plural"] = plural
+ n.Data["Terms"] = s.Taxonomies[plural]
+ // keep the following just for legacy reasons
+ n.Data["OrderedIndex"] = n.Data["Terms"]
+ n.Data["Index"] = n.Data["Terms"]
+ layouts := []string{"taxonomy/" + singular + ".terms.html", "_default/terms.html", "indexes/indexes.html"}+ layouts = s.appendThemeTemplates(layouts)
+ if s.layoutExists(layouts...) {err := s.render(n, plural+"/index.html", layouts...)
if err != nil {return err
@@ -497,6 +535,7 @@
}
}
}
+
return
}
@@ -508,8 +547,9 @@
s.setUrls(n, section)
n.Date = data[0].Page.Date
n.Data["Pages"] = data.Pages()
+ layouts := []string{"section/" + section + ".html", "_default/section.html", "_default/list.html", "indexes/" + section + ".html", "_default/indexes.html"}- err := s.render(n, section, "section/"+section+".html", "indexes/"+section+".html", "_default/section.html", "_default/list.html", "_default/indexes.html")
+ err := s.render(n, section, s.appendThemeTemplates(layouts)...)
if err != nil {return err
}
@@ -516,9 +556,9 @@
if !viper.GetBool("DisableRSS") {// XML Feed
+ rssLayouts := []string{"section/" + section + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}s.setUrls(n, section+".xml")
- err = s.render(n, section+".xml", "rss.xml", "_internal/_default/rss.xml")
- //TODO add section specific rss
+ err = s.render(n, section+".xml", s.appendThemeTemplates(rssLayouts)...)
if err != nil {return err
}
@@ -532,7 +572,8 @@
n.Title = n.Site.Title
s.setUrls(n, "/")
n.Data["Pages"] = s.Pages
- err := s.render(n, "/", "index.html")
+ layouts := []string{"index.html"}+ err := s.render(n, "/", s.appendThemeTemplates(layouts)...)
if err != nil {return err
}
@@ -550,9 +591,13 @@
if len(s.Pages) > 0 {n.Date = s.Pages[0].Date
}
- err := s.render(n, ".xml", "rss.xml", "_internal/_default/rss.xml")
- if err != nil {- return err
+
+ if !viper.GetBool("DisableRSS") {+ rssLayouts := []string{"rss.xml", "_default/rss.xml", "_internal/_default/rss.xml"}+ err := s.render(n, ".xml", s.appendThemeTemplates(rssLayouts)...)
+ if err != nil {+ return err
+ }
}
}
@@ -560,7 +605,9 @@
n.Url = helpers.Urlize("404.html")n.Title = "404 Page not found"
n.Permalink = s.permalink("404.html")- return s.render(n, "404.html", "404.html")
+
+ layouts := []string{"404.html"}+ return s.render(n, "404.html", s.appendThemeTemplates(layouts)...)
}
return nil
--- a/template/bundle/template.go
+++ b/template/bundle/template.go
@@ -138,6 +138,7 @@
Templates() []*template.Template
New(name string) *template.Template
LoadTemplates(absPath string)
+ LoadTemplatesWithPrefix(absPath, prefix string)
AddTemplate(name, tpl string) error
AddInternalTemplate(prefix, name, tpl string) error
AddInternalShortcode(name, tpl string) error
@@ -211,12 +212,7 @@
if err != nil {return err
}
- s := string(b)
- _, err = t.New(name).Parse(s)
- if err != nil {- t.errors = append(t.errors, &templateErr{name: name, err: err})- }
- return err
+ return t.AddTemplate(name, string(b))
}
func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string {@@ -227,7 +223,7 @@
return filepath.Base(path)[0] == '.'
}
-func (t *GoHtmlTemplate) LoadTemplates(absPath string) {+func (t *GoHtmlTemplate) loadTemplates(absPath string, prefix string) { walker := func(path string, fi os.FileInfo, err error) error { if err != nil {return nil
@@ -240,6 +236,11 @@
tplName := t.generateTemplateNameFrom(absPath, path)
+ if prefix != "" {+ tplName = strings.Trim(prefix, "/") + "/" + tplName
+ }
+
+ // TODO move this into the AddTemplateFile function
if strings.HasSuffix(path, ".amber") {compiler := amber.New()
// Parse the input file
@@ -247,7 +248,6 @@
return nil
}
- // note t.New(tplName)
if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {return err
}
@@ -260,4 +260,12 @@
}
filepath.Walk(absPath, walker)
+}
+
+func (t *GoHtmlTemplate) LoadTemplatesWithPrefix(absPath string, prefix string) {+ t.loadTemplates(absPath, prefix)
+}
+
+func (t *GoHtmlTemplate) LoadTemplates(absPath string) {+ t.loadTemplates(absPath, "")
}
--
⑨