mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Preliminary Theme Support
This commit is contained in:
parent
c0a046cbfb
commit
8afff8c7c4
3 changed files with 120 additions and 38 deletions
|
@ -49,7 +49,7 @@ Complete documentation is available at http://hugo.spf13.com`,
|
||||||
var hugoCmdV *cobra.Command
|
var hugoCmdV *cobra.Command
|
||||||
|
|
||||||
var BuildWatch, Draft, UglyUrls, Verbose, Logging, VerboseLog, DisableRSS bool
|
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() {
|
func Execute() {
|
||||||
AddCommands()
|
AddCommands()
|
||||||
|
@ -68,6 +68,7 @@ func init() {
|
||||||
HugoCmd.PersistentFlags().BoolVar(&DisableRSS, "disableRSS", false, "Do not build RSS files")
|
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(&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(&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().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
||||||
HugoCmd.PersistentFlags().BoolVar(&UglyUrls, "uglyurls", false, "if true, use /filename.html instead of /filename/")
|
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/")
|
HugoCmd.PersistentFlags().StringVarP(&BaseUrl, "base-url", "b", "", "hostname (and path) to the root eg. http://spf13.com/")
|
||||||
|
@ -126,6 +127,11 @@ func InitializeConfig() {
|
||||||
}
|
}
|
||||||
viper.Set("BaseUrl", BaseUrl)
|
viper.Set("BaseUrl", BaseUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if Theme != "" {
|
||||||
|
viper.Set("theme", Theme)
|
||||||
|
}
|
||||||
|
|
||||||
if Destination != "" {
|
if Destination != "" {
|
||||||
viper.Set("PublishDir", Destination)
|
viper.Set("PublishDir", Destination)
|
||||||
}
|
}
|
||||||
|
@ -176,10 +182,24 @@ func build(watches ...bool) {
|
||||||
func copyStatic() error {
|
func copyStatic() error {
|
||||||
staticDir := helpers.AbsPathify(viper.GetString("StaticDir")) + "/"
|
staticDir := helpers.AbsPathify(viper.GetString("StaticDir")) + "/"
|
||||||
if _, err := os.Stat(staticDir); os.IsNotExist(err) {
|
if _, err := os.Stat(staticDir); os.IsNotExist(err) {
|
||||||
|
jww.ERROR.Println("Unable to find Static Directory:", viper.GetString("theme"), "in", staticDir)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
publishDir := helpers.AbsPathify(viper.GetString("PublishDir")) + "/"
|
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
|
// Copy Static to Destination
|
||||||
jww.INFO.Println("syncing from", staticDir, "to", publishDir)
|
jww.INFO.Println("syncing from", staticDir, "to", publishDir)
|
||||||
return fsync.Sync(publishDir, staticDir)
|
return fsync.Sync(publishDir, staticDir)
|
||||||
|
@ -202,10 +222,17 @@ func getDirList() []string {
|
||||||
filepath.Walk(helpers.AbsPathify(viper.GetString("ContentDir")), walker)
|
filepath.Walk(helpers.AbsPathify(viper.GetString("ContentDir")), walker)
|
||||||
filepath.Walk(helpers.AbsPathify(viper.GetString("LayoutDir")), walker)
|
filepath.Walk(helpers.AbsPathify(viper.GetString("LayoutDir")), walker)
|
||||||
filepath.Walk(helpers.AbsPathify(viper.GetString("StaticDir")), walker)
|
filepath.Walk(helpers.AbsPathify(viper.GetString("StaticDir")), walker)
|
||||||
|
if themeSet() {
|
||||||
|
filepath.Walk(helpers.AbsPathify("themes/"+viper.GetString("theme")), walker)
|
||||||
|
}
|
||||||
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func themeSet() bool {
|
||||||
|
return viper.GetString("theme") != ""
|
||||||
|
}
|
||||||
|
|
||||||
func buildSite(watching ...bool) (err error) {
|
func buildSite(watching ...bool) (err error) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
site := &hugolib.Site{}
|
site := &hugolib.Site{}
|
||||||
|
|
105
hugolib/site.go
105
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");
|
// Licensed under the Simple Public License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -132,6 +132,9 @@ func (s *Site) Analyze() {
|
||||||
func (s *Site) prepTemplates() {
|
func (s *Site) prepTemplates() {
|
||||||
s.Tmpl = bundle.NewTemplate()
|
s.Tmpl = bundle.NewTemplate()
|
||||||
s.Tmpl.LoadTemplates(s.absLayoutDir())
|
s.Tmpl.LoadTemplates(s.absLayoutDir())
|
||||||
|
if s.hasTheme() {
|
||||||
|
s.Tmpl.LoadTemplatesWithPrefix(s.absThemeDir()+"/layouts", "theme")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) addTemplate(name, data string) error {
|
func (s *Site) addTemplate(name, data string) error {
|
||||||
|
@ -244,6 +247,14 @@ func (s *Site) initializeSiteInfo() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
func (s *Site) absLayoutDir() string {
|
||||||
return helpers.AbsPathify(viper.GetString("LayoutDir"))
|
return helpers.AbsPathify(viper.GetString("LayoutDir"))
|
||||||
}
|
}
|
||||||
|
@ -422,7 +433,7 @@ func (s *Site) RenderPages() (err error) {
|
||||||
layouts = append(layouts, "_default/single.html")
|
layouts = append(layouts, "_default/single.html")
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.render(p, p.TargetPath(), layouts...)
|
return s.render(p, p.TargetPath(), s.appendThemeTemplates(layouts)...)
|
||||||
}(page)
|
}(page)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
@ -433,6 +444,34 @@ func (s *Site) RenderPages() (err error) {
|
||||||
return nil
|
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
|
// Render the listing pages based on the meta data
|
||||||
// each unique term within a taxonomy will have a page created
|
// each unique term within a taxonomy will have a page created
|
||||||
func (s *Site) RenderTaxonomiesLists() (err error) {
|
func (s *Site) RenderTaxonomiesLists() (err error) {
|
||||||
|
@ -451,8 +490,8 @@ func (s *Site) RenderTaxonomiesLists() (err error) {
|
||||||
n.Date = o[0].Page.Date
|
n.Date = o[0].Page.Date
|
||||||
n.Data[singular] = o
|
n.Data[singular] = o
|
||||||
n.Data["Pages"] = o.Pages()
|
n.Data["Pages"] = o.Pages()
|
||||||
err = s.render(n, base+".html", "taxonomies/"+singular+".html", "indexes/"+singular+".html")
|
layouts := []string{"taxonomy/" + singular + ".html", "indexes/" + singular + ".html", "_default/taxonomy.html", "_default/list.html"}
|
||||||
//TODO add , "_default/taxonomy.html", "_default/list.html"
|
err = s.render(n, base+".html", s.appendThemeTemplates(layouts)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -460,7 +499,8 @@ func (s *Site) RenderTaxonomiesLists() (err error) {
|
||||||
if !viper.GetBool("DisableRSS") {
|
if !viper.GetBool("DisableRSS") {
|
||||||
// XML Feed
|
// XML Feed
|
||||||
s.setUrls(n, base+".xml")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -475,28 +515,27 @@ func (s *Site) RenderTaxonomiesLists() (err error) {
|
||||||
|
|
||||||
// Render a page per taxonomy that lists the terms for that taxonomy
|
// Render a page per taxonomy that lists the terms for that taxonomy
|
||||||
func (s *Site) RenderListsOfTaxonomyTerms() (err error) {
|
func (s *Site) RenderListsOfTaxonomyTerms() (err error) {
|
||||||
layouts := []string{"taxonomies/termslist.html", "indexes/indexes.html"}
|
taxonomies := viper.GetStringMapString("Taxonomies")
|
||||||
// TODO add "_default/termsList.html", "_default/termslist.html"
|
for singular, plural := range taxonomies {
|
||||||
// TODO add support for unique taxonomy terms list (`single`terms.html)
|
n := s.NewNode()
|
||||||
if s.layoutExists(layouts...) {
|
n.Title = strings.Title(plural)
|
||||||
taxonomies := viper.GetStringMapString("Taxonomies")
|
s.setUrls(n, plural)
|
||||||
for singular, plural := range taxonomies {
|
n.Data["Singular"] = singular
|
||||||
n := s.NewNode()
|
n.Data["Plural"] = plural
|
||||||
n.Title = strings.Title(plural)
|
n.Data["Terms"] = s.Taxonomies[plural]
|
||||||
s.setUrls(n, plural)
|
// keep the following just for legacy reasons
|
||||||
n.Data["Singular"] = singular
|
n.Data["OrderedIndex"] = n.Data["Terms"]
|
||||||
n.Data["Plural"] = plural
|
n.Data["Index"] = n.Data["Terms"]
|
||||||
n.Data["Terms"] = s.Taxonomies[plural]
|
layouts := []string{"taxonomy/" + singular + ".terms.html", "_default/terms.html", "indexes/indexes.html"}
|
||||||
// keep the following just for legacy reasons
|
layouts = s.appendThemeTemplates(layouts)
|
||||||
n.Data["OrderedIndex"] = n.Data["Terms"]
|
if s.layoutExists(layouts...) {
|
||||||
n.Data["Index"] = n.Data["Terms"]
|
|
||||||
|
|
||||||
err := s.render(n, plural+"/index.html", layouts...)
|
err := s.render(n, plural+"/index.html", layouts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,17 +547,18 @@ func (s *Site) RenderSectionLists() error {
|
||||||
s.setUrls(n, section)
|
s.setUrls(n, section)
|
||||||
n.Date = data[0].Page.Date
|
n.Date = data[0].Page.Date
|
||||||
n.Data["Pages"] = data.Pages()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !viper.GetBool("DisableRSS") {
|
if !viper.GetBool("DisableRSS") {
|
||||||
// XML Feed
|
// XML Feed
|
||||||
|
rssLayouts := []string{"section/" + section + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}
|
||||||
s.setUrls(n, section+".xml")
|
s.setUrls(n, section+".xml")
|
||||||
err = s.render(n, section+".xml", "rss.xml", "_internal/_default/rss.xml")
|
err = s.render(n, section+".xml", s.appendThemeTemplates(rssLayouts)...)
|
||||||
//TODO add section specific rss
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -532,7 +572,8 @@ func (s *Site) RenderHomePage() error {
|
||||||
n.Title = n.Site.Title
|
n.Title = n.Site.Title
|
||||||
s.setUrls(n, "/")
|
s.setUrls(n, "/")
|
||||||
n.Data["Pages"] = s.Pages
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -550,9 +591,13 @@ func (s *Site) RenderHomePage() error {
|
||||||
if len(s.Pages) > 0 {
|
if len(s.Pages) > 0 {
|
||||||
n.Date = s.Pages[0].Date
|
n.Date = s.Pages[0].Date
|
||||||
}
|
}
|
||||||
err := s.render(n, ".xml", "rss.xml", "_internal/_default/rss.xml")
|
|
||||||
if err != nil {
|
if !viper.GetBool("DisableRSS") {
|
||||||
return err
|
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 @@ func (s *Site) RenderHomePage() error {
|
||||||
n.Url = helpers.Urlize("404.html")
|
n.Url = helpers.Urlize("404.html")
|
||||||
n.Title = "404 Page not found"
|
n.Title = "404 Page not found"
|
||||||
n.Permalink = s.permalink("404.html")
|
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
|
return nil
|
||||||
|
|
|
@ -138,6 +138,7 @@ type Template interface {
|
||||||
Templates() []*template.Template
|
Templates() []*template.Template
|
||||||
New(name string) *template.Template
|
New(name string) *template.Template
|
||||||
LoadTemplates(absPath string)
|
LoadTemplates(absPath string)
|
||||||
|
LoadTemplatesWithPrefix(absPath, prefix string)
|
||||||
AddTemplate(name, tpl string) error
|
AddTemplate(name, tpl string) error
|
||||||
AddInternalTemplate(prefix, name, tpl string) error
|
AddInternalTemplate(prefix, name, tpl string) error
|
||||||
AddInternalShortcode(name, tpl string) error
|
AddInternalShortcode(name, tpl string) error
|
||||||
|
@ -211,12 +212,7 @@ func (t *GoHtmlTemplate) AddTemplateFile(name, path string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s := string(b)
|
return t.AddTemplate(name, string(b))
|
||||||
_, err = t.New(name).Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
t.errors = append(t.errors, &templateErr{name: name, err: err})
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string {
|
func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string {
|
||||||
|
@ -227,7 +223,7 @@ func ignoreDotFile(path string) bool {
|
||||||
return filepath.Base(path)[0] == '.'
|
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 {
|
walker := func(path string, fi os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -240,6 +236,11 @@ func (t *GoHtmlTemplate) LoadTemplates(absPath string) {
|
||||||
|
|
||||||
tplName := t.generateTemplateNameFrom(absPath, path)
|
tplName := t.generateTemplateNameFrom(absPath, path)
|
||||||
|
|
||||||
|
if prefix != "" {
|
||||||
|
tplName = strings.Trim(prefix, "/") + "/" + tplName
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO move this into the AddTemplateFile function
|
||||||
if strings.HasSuffix(path, ".amber") {
|
if strings.HasSuffix(path, ".amber") {
|
||||||
compiler := amber.New()
|
compiler := amber.New()
|
||||||
// Parse the input file
|
// Parse the input file
|
||||||
|
@ -247,7 +248,6 @@ func (t *GoHtmlTemplate) LoadTemplates(absPath string) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// note t.New(tplName)
|
|
||||||
if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {
|
if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -261,3 +261,11 @@ func (t *GoHtmlTemplate) LoadTemplates(absPath string) {
|
||||||
|
|
||||||
filepath.Walk(absPath, walker)
|
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, "")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue