shithub: hugo

Download patch

ref: dbb83f925a7cb256b69b158e2caf0d99e3c7c5e6
parent: 4aaed87dd97b085b1505e53b7d4564aa8f7f18ef
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Mar 22 07:34:17 EDT 2017

hugolib: Read default output formats from site config

--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -177,7 +177,7 @@
 		for _, p := range s.Pages {
 			// May have been set in front matter
 			if len(p.outputFormats) == 0 {
-				p.outputFormats = s.defaultOutputDefinitions.ForKind(p.Kind)
+				p.outputFormats = s.outputFormats[p.Kind]
 			}
 			if err := p.initTargetPathDescriptor(); err != nil {
 				return err
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -859,7 +859,7 @@
 func (p *Page) initURLs() error {
 	// TODO(bep) output
 	if len(p.outputFormats) == 0 {
-		p.outputFormats = p.s.defaultOutputDefinitions.ForKind(p.Kind)
+		p.outputFormats = p.s.outputFormats[p.Kind]
 	}
 	rel := p.createRelativePermalink()
 	p.permalink = p.s.permalink(rel)
--- a/hugolib/page_output.go
+++ b/hugolib/page_output.go
@@ -45,7 +45,6 @@
 		return "", err
 	}
 	return tp, nil
-
 }
 
 func newPageOutput(p *Page, createCopy bool, f output.Format) (*PageOutput, error) {
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -108,7 +108,10 @@
 
 	disabledKinds map[string]bool
 
-	defaultOutputDefinitions siteOutputDefinitions
+	// Output formats defined in site config per Page Kind, or some defaults
+	// if not set.
+	// Output formats defined in Page front matter will override these.
+	outputFormats map[string]output.Formats
 
 	// Logger etc.
 	*deps.Deps `json:"-"`
@@ -124,12 +127,12 @@
 // reset returns a new Site prepared for rebuild.
 func (s *Site) reset() *Site {
 	return &Site{Deps: s.Deps,
-		layoutHandler:            output.NewLayoutHandler(s.PathSpec.ThemeSet()),
-		disabledKinds:            s.disabledKinds,
-		defaultOutputDefinitions: s.defaultOutputDefinitions,
-		Language:                 s.Language,
-		owner:                    s.owner,
-		PageCollections:          newPageCollections()}
+		layoutHandler:   output.NewLayoutHandler(s.PathSpec.ThemeSet()),
+		disabledKinds:   s.disabledKinds,
+		outputFormats:   s.outputFormats,
+		Language:        s.Language,
+		owner:           s.owner,
+		PageCollections: newPageCollections()}
 }
 
 // newSite creates a new site with the given configuration.
@@ -145,14 +148,18 @@
 		disabledKinds[disabled] = true
 	}
 
-	outputDefs := createSiteOutputDefinitions(cfg.Cfg)
+	outputFormats, err := createSiteOutputFormats(cfg.Language)
 
+	if err != nil {
+		return nil, err
+	}
+
 	s := &Site{
-		PageCollections:          c,
-		layoutHandler:            output.NewLayoutHandler(cfg.Cfg.GetString("themesDir") != ""),
-		Language:                 cfg.Language,
-		disabledKinds:            disabledKinds,
-		defaultOutputDefinitions: outputDefs,
+		PageCollections: c,
+		layoutHandler:   output.NewLayoutHandler(cfg.Cfg.GetString("themesDir") != ""),
+		Language:        cfg.Language,
+		disabledKinds:   disabledKinds,
+		outputFormats:   outputFormats,
 	}
 
 	s.Info = newSiteInfo(siteBuilderCfg{s: s, pageCollections: c, language: s.Language})
@@ -2007,7 +2014,7 @@
 		sections: sections,
 		s:        s}
 
-	p.outputFormats = p.s.defaultOutputDefinitions.ForKind(typ)
+	p.outputFormats = p.s.outputFormats[p.Kind]
 
 	return p
 
--- a/hugolib/site_output.go
+++ b/hugolib/site_output.go
@@ -14,56 +14,81 @@
 package hugolib
 
 import (
+	"fmt"
 	"path"
 	"strings"
 
+	"github.com/spf13/cast"
 	"github.com/spf13/hugo/config"
 	"github.com/spf13/hugo/output"
 )
 
-type siteOutputDefinitions []siteOutputDefinition
+func createSiteOutputFormats(cfg config.Provider) (map[string]output.Formats, error) {
+	if !cfg.IsSet("outputs") {
+		return createDefaultOutputFormats(cfg)
+	}
 
-type siteOutputDefinition struct {
-	// What Kinds of pages are excluded in this definition.
-	// A blank strings means NONE.
-	// Comma separated list (for now).
-	ExcludedKinds string
+	outFormats := make(map[string]output.Formats)
 
-	Outputs []output.Format
-}
+	outputs := cfg.GetStringMap("outputs")
 
-func (defs siteOutputDefinitions) ForKind(kind string) []output.Format {
-	var result []output.Format
+	if outputs == nil || len(outputs) == 0 {
+		// TODO(bep) outputs log a warning?
+		return outFormats, nil
+	}
 
-	for _, def := range defs {
-		if def.ExcludedKinds == "" || !strings.Contains(def.ExcludedKinds, kind) {
-			result = append(result, def.Outputs...)
+	for k, v := range outputs {
+		var formats output.Formats
+		vals := cast.ToStringSlice(v)
+		for _, format := range vals {
+			f, found := output.GetFormat(format)
+			if !found {
+				return nil, fmt.Errorf("Failed to resolve output format %q from site config", format)
+			}
+			formats = append(formats, f)
 		}
+
+		if len(formats) > 0 {
+			outFormats[k] = formats
+		}
 	}
 
-	return result
-}
+	// Make sure every kind has at least one output format
+	for _, kind := range allKinds {
+		if _, found := outFormats[kind]; !found {
+			outFormats[kind] = output.Formats{output.HTMLType}
+		}
+	}
 
-func createSiteOutputDefinitions(cfg config.Provider) siteOutputDefinitions {
+	return outFormats, nil
 
-	var defs siteOutputDefinitions
+}
 
-	// All have HTML
-	defs = append(defs, siteOutputDefinition{ExcludedKinds: "", Outputs: []output.Format{output.HTMLType}})
+func createDefaultOutputFormats(cfg config.Provider) (map[string]output.Formats, error) {
+	outFormats := make(map[string]output.Formats)
+	for _, kind := range allKinds {
+		var formats output.Formats
+		// All have HTML
+		formats = append(formats, output.HTMLType)
 
-	// TODO(bep) output deprecate rssURI
-	rssBase := cfg.GetString("rssURI")
-	if rssBase == "" {
-		rssBase = "index"
-	}
+		// All but page have RSS
+		if kind != KindPage {
+			// TODO(bep) output deprecate rssURI
+			rssBase := cfg.GetString("rssURI")
+			if rssBase == "" {
+				rssBase = "index"
+			}
 
-	// RSS has now a well defined media type, so strip any suffix provided
-	rssBase = strings.TrimSuffix(rssBase, path.Ext(rssBase))
-	rssType := output.RSSType
-	rssType.BaseName = rssBase
+			// RSS has now a well defined media type, so strip any suffix provided
+			rssBase = strings.TrimSuffix(rssBase, path.Ext(rssBase))
+			rssType := output.RSSType
+			rssType.BaseName = rssBase
+			formats = append(formats, rssType)
 
-	// Some have RSS
-	defs = append(defs, siteOutputDefinition{ExcludedKinds: "page", Outputs: []output.Format{rssType}})
+		}
 
-	return defs
+		outFormats[kind] = formats
+	}
+
+	return outFormats, nil
 }
--- a/hugolib/site_output_test.go
+++ b/hugolib/site_output_test.go
@@ -27,23 +27,25 @@
 	"github.com/spf13/viper"
 )
 
-func TestDefaultOutputDefinitions(t *testing.T) {
+func TestDefaultOutputFormats(t *testing.T) {
 	t.Parallel()
-	defs := createSiteOutputDefinitions(viper.New())
+	defs, err := createDefaultOutputFormats(viper.New())
 
+	require.NoError(t, err)
+
 	tests := []struct {
 		name string
 		kind string
-		want []output.Format
+		want output.Formats
 	}{
-		{"RSS not for regular pages", KindPage, []output.Format{output.HTMLType}},
-		{"Home Sweet Home", KindHome, []output.Format{output.HTMLType, output.RSSType}},
+		{"RSS not for regular pages", KindPage, output.Formats{output.HTMLType}},
+		{"Home Sweet Home", KindHome, output.Formats{output.HTMLType, output.RSSType}},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			if got := defs.ForKind(tt.kind); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("siteOutputDefinitions.ForKind(%v) = %v, want %v", tt.kind, got, tt.want)
+			if got := defs[tt.kind]; !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("createDefaultOutputFormats(%v) = %v, want %v", tt.kind, got, tt.want)
 			}
 		})
 	}
@@ -57,6 +59,7 @@
 	}
 }
 
+// TODO(bep) output add test for site outputs config
 func doTestSiteWithPageOutputs(t *testing.T, outputs []string) {
 	t.Parallel()
 
--- a/media/mediaType_test.go
+++ b/media/mediaType_test.go
@@ -24,7 +24,7 @@
 	require.Equal(t, "html", HTMLType.SubType)
 	require.Equal(t, "html", HTMLType.Suffix)
 
-	require.Equal(t, "text/html", HTMLType.MainType())
+	require.Equal(t, "text/html", HTMLType.Type())
 	require.Equal(t, "text/html+html", HTMLType.String())
 
 	require.Equal(t, "application", RSSType.MainType)
@@ -31,7 +31,7 @@
 	require.Equal(t, "rss", RSSType.SubType)
 	require.Equal(t, "xml", RSSType.Suffix)
 
-	require.Equal(t, "application/rss", RSSType.MainType())
+	require.Equal(t, "application/rss", RSSType.Type())
 	require.Equal(t, "application/rss+xml", RSSType.String())
 
 }
--- a/output/layout_base.go
+++ b/output/layout_base.go
@@ -56,11 +56,11 @@
 	ContainsAny func(filename string, subslices [][]byte) (bool, error)
 }
 
-func CreateTemplateID(d TemplateLookupDescriptor) (TemplateNames, error) {
+func CreateTemplateNames(d TemplateLookupDescriptor) (TemplateNames, error) {
 
 	var id TemplateNames
 
-	name := filepath.FromSlash(d.RelPath)
+	name := filepath.ToSlash(d.RelPath)
 
 	if d.Prefix != "" {
 		name = strings.Trim(d.Prefix, "/") + "/" + name
--- a/output/layout_base_test.go
+++ b/output/layout_base_test.go
@@ -124,6 +124,8 @@
 	} {
 		t.Run(this.name, func(t *testing.T) {
 
+			this.basePathMatchStrings = filepath.FromSlash(this.basePathMatchStrings)
+
 			fileExists := func(filename string) (bool, error) {
 				stringsToMatch := strings.Split(this.basePathMatchStrings, "|")
 				for _, s := range stringsToMatch {
@@ -148,7 +150,7 @@
 			this.expect.MasterFilename = filepath.FromSlash(this.expect.MasterFilename)
 			this.expect.OverlayFilename = filepath.FromSlash(this.expect.OverlayFilename)
 
-			id, err := CreateTemplateID(this.d)
+			id, err := CreateTemplateNames(this.d)
 
 			require.NoError(t, err)
 			require.Equal(t, this.expect, id, this.name)
--- a/tpl/tplimpl/template.go
+++ b/tpl/tplimpl/template.go
@@ -508,7 +508,7 @@
 				},
 			}
 
-			tplID, err := output.CreateTemplateID(descriptor)
+			tplID, err := output.CreateTemplateNames(descriptor)
 			if err != nil {
 				t.Log.ERROR.Printf("Failed to resolve template in path %q: %s", path, err)
 				return nil