shithub: hugo

Download patch

ref: f8dc47eeffa847fd0b51e376da355e3d957848a6
parent: ae3fa349de6daf1bbcd09ffc859d6b2e44764795
author: Bjørn Erik Pedersen <[email protected]>
date: Sat Mar 10 06:45:29 EST 2018

Allow partial redefinition of the ouputs config

Fixes #4487

--- a/hugolib/site_output.go
+++ b/hugolib/site_output.go
@@ -24,9 +24,46 @@
 	"github.com/spf13/cast"
 )
 
+func createDefaultOutputFormats(allFormats output.Formats, cfg config.Provider) map[string]output.Formats {
+	rssOut, _ := allFormats.GetByName(output.RSSFormat.Name)
+	htmlOut, _ := allFormats.GetByName(output.HTMLFormat.Name)
+	robotsOut, _ := allFormats.GetByName(output.RobotsTxtFormat.Name)
+	sitemapOut, _ := allFormats.GetByName(output.SitemapFormat.Name)
+
+	// TODO(bep) this mumbo jumbo is deprecated and should be removed, but there are tests that
+	// depends on this, so that will have to wait.
+	rssBase := cfg.GetString("rssURI")
+	if rssBase == "" || rssBase == "index.xml" {
+		rssBase = rssOut.BaseName
+	} else {
+		// Remove in Hugo 0.36.
+		helpers.Deprecated("Site config", "rssURI", "Set baseName in outputFormats.RSS", true)
+		// RSS has now a well defined media type, so strip any suffix provided
+		rssBase = strings.TrimSuffix(rssBase, path.Ext(rssBase))
+	}
+
+	rssOut.BaseName = rssBase
+
+	return map[string]output.Formats{
+		KindPage:         output.Formats{htmlOut},
+		KindHome:         output.Formats{htmlOut, rssOut},
+		KindSection:      output.Formats{htmlOut, rssOut},
+		KindTaxonomy:     output.Formats{htmlOut, rssOut},
+		KindTaxonomyTerm: output.Formats{htmlOut, rssOut},
+		// Below are for conistency. They are currently not used during rendering.
+		kindRSS:       output.Formats{rssOut},
+		kindSitemap:   output.Formats{sitemapOut},
+		kindRobotsTXT: output.Formats{robotsOut},
+		kind404:       output.Formats{htmlOut},
+	}
+
+}
+
 func createSiteOutputFormats(allFormats output.Formats, cfg config.Provider) (map[string]output.Formats, error) {
+	defaultOutputFormats := createDefaultOutputFormats(allFormats, cfg)
+
 	if !cfg.IsSet("outputs") {
-		return createDefaultOutputFormats(allFormats, cfg)
+		return defaultOutputFormats, nil
 	}
 
 	outFormats := make(map[string]output.Formats)
@@ -37,6 +74,8 @@
 		return outFormats, nil
 	}
 
+	seen := make(map[string]bool)
+
 	for k, v := range outputs {
 		var formats output.Formats
 		vals := cast.ToStringSlice(v)
@@ -48,52 +87,21 @@
 			formats = append(formats, f)
 		}
 
+		// This effectively prevents empty outputs entries for a given Kind.
+		// We need at least one.
 		if len(formats) > 0 {
+			seen[k] = true
 			outFormats[k] = formats
 		}
 	}
 
-	// Make sure every kind has at least one output format
-	for _, kind := range allKinds {
-		if _, found := outFormats[kind]; !found {
-			outFormats[kind] = output.Formats{output.HTMLFormat}
+	// Add defaults for the entries not provided by the user.
+	for k, v := range defaultOutputFormats {
+		if !seen[k] {
+			outFormats[k] = v
 		}
 	}
 
 	return outFormats, nil
 
-}
-
-func createDefaultOutputFormats(allFormats output.Formats, cfg config.Provider) (map[string]output.Formats, error) {
-	outFormats := make(map[string]output.Formats)
-	rssOut, _ := allFormats.GetByName(output.RSSFormat.Name)
-	htmlOut, _ := allFormats.GetByName(output.HTMLFormat.Name)
-
-	for _, kind := range allKinds {
-		var formats output.Formats
-		// All have HTML
-		formats = append(formats, htmlOut)
-
-		// All but page have RSS
-		if kind != KindPage {
-
-			rssBase := cfg.GetString("rssURI")
-			if rssBase == "" || rssBase == "index.xml" {
-				rssBase = rssOut.BaseName
-			} else {
-				// Remove in Hugo 0.36.
-				helpers.Deprecated("Site config", "rssURI", "Set baseName in outputFormats.RSS", true)
-				// RSS has now a well defined media type, so strip any suffix provided
-				rssBase = strings.TrimSuffix(rssBase, path.Ext(rssBase))
-			}
-
-			rssOut.BaseName = rssBase
-			formats = append(formats, rssOut)
-
-		}
-
-		outFormats[kind] = formats
-	}
-
-	return outFormats, nil
 }
--- a/hugolib/site_output_test.go
+++ b/hugolib/site_output_test.go
@@ -14,7 +14,6 @@
 package hugolib
 
 import (
-	"reflect"
 	"strings"
 	"testing"
 
@@ -29,54 +28,6 @@
 	"github.com/spf13/viper"
 )
 
-func TestDefaultOutputFormats(t *testing.T) {
-	t.Parallel()
-	defs, err := createDefaultOutputFormats(output.DefaultFormats, viper.New())
-
-	require.NoError(t, err)
-
-	tests := []struct {
-		name string
-		kind string
-		want output.Formats
-	}{
-		{"RSS not for regular pages", KindPage, output.Formats{output.HTMLFormat}},
-		{"Home Sweet Home", KindHome, output.Formats{output.HTMLFormat, output.RSSFormat}},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := defs[tt.kind]; !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("createDefaultOutputFormats(%v) = %v, want %v", tt.kind, got, tt.want)
-			}
-		})
-	}
-}
-
-func TestDefaultOutputFormatsWithOverrides(t *testing.T) {
-	t.Parallel()
-
-	htmlOut := output.HTMLFormat
-	htmlOut.BaseName = "htmlindex"
-	rssOut := output.RSSFormat
-	rssOut.BaseName = "feed"
-
-	defs, err := createDefaultOutputFormats(output.Formats{htmlOut, rssOut}, viper.New())
-
-	homeDefs := defs[KindHome]
-
-	rss, found := homeDefs.GetByName("RSS")
-	require.True(t, found)
-	require.Equal(t, rss.BaseName, "feed")
-
-	html, found := homeDefs.GetByName("HTML")
-	require.True(t, found)
-	require.Equal(t, html.BaseName, "htmlindex")
-
-	require.NoError(t, err)
-
-}
-
 func TestSiteWithPageOutputs(t *testing.T) {
 	for _, outputs := range [][]string{{"html", "json", "calendar"}, {"json"}} {
 		t.Run(fmt.Sprintf("%v", outputs), func(t *testing.T) {
@@ -372,4 +323,84 @@
 	require.Equal(t, "/blog/nosuffixbase.", outputs.Get("NOS").RelPermalink())
 	require.Equal(t, "/blog/customdelimbase_del", outputs.Get("CUS").RelPermalink())
 
+}
+
+func TestCreateSiteOutputFormats(t *testing.T) {
+	assert := require.New(t)
+
+	outputsConfig := map[string]interface{}{
+		KindHome:    []string{"HTML", "JSON"},
+		KindSection: []string{"JSON"},
+	}
+
+	cfg := viper.New()
+	cfg.Set("outputs", outputsConfig)
+
+	outputs, err := createSiteOutputFormats(output.DefaultFormats, cfg)
+	assert.NoError(err)
+	assert.Equal(output.Formats{output.JSONFormat}, outputs[KindSection])
+	assert.Equal(output.Formats{output.HTMLFormat, output.JSONFormat}, outputs[KindHome])
+
+	// Defaults
+	assert.Equal(output.Formats{output.HTMLFormat, output.RSSFormat}, outputs[KindTaxonomy])
+	assert.Equal(output.Formats{output.HTMLFormat, output.RSSFormat}, outputs[KindTaxonomyTerm])
+	assert.Equal(output.Formats{output.HTMLFormat}, outputs[KindPage])
+
+	// These aren't (currently) in use when rendering in Hugo,
+	// but the pages needs to be assigned an output format,
+	// so these should also be correct/sensible.
+	assert.Equal(output.Formats{output.RSSFormat}, outputs[kindRSS])
+	assert.Equal(output.Formats{output.SitemapFormat}, outputs[kindSitemap])
+	assert.Equal(output.Formats{output.RobotsTxtFormat}, outputs[kindRobotsTXT])
+	assert.Equal(output.Formats{output.HTMLFormat}, outputs[kind404])
+
+}
+
+func TestCreateSiteOutputFormatsInvalidConfig(t *testing.T) {
+	assert := require.New(t)
+
+	outputsConfig := map[string]interface{}{
+		KindHome: []string{"FOO", "JSON"},
+	}
+
+	cfg := viper.New()
+	cfg.Set("outputs", outputsConfig)
+
+	_, err := createSiteOutputFormats(output.DefaultFormats, cfg)
+	assert.Error(err)
+}
+
+func TestCreateSiteOutputFormatsEmptyConfig(t *testing.T) {
+	assert := require.New(t)
+
+	outputsConfig := map[string]interface{}{
+		KindHome: []string{},
+	}
+
+	cfg := viper.New()
+	cfg.Set("outputs", outputsConfig)
+
+	outputs, err := createSiteOutputFormats(output.DefaultFormats, cfg)
+	assert.NoError(err)
+	assert.Equal(output.Formats{output.HTMLFormat, output.RSSFormat}, outputs[KindHome])
+}
+
+func TestCreateSiteOutputFormatsCustomFormats(t *testing.T) {
+	assert := require.New(t)
+
+	outputsConfig := map[string]interface{}{
+		KindHome: []string{},
+	}
+
+	cfg := viper.New()
+	cfg.Set("outputs", outputsConfig)
+
+	var (
+		customRSS  = output.Format{Name: "RSS", BaseName: "customRSS"}
+		customHTML = output.Format{Name: "HTML", BaseName: "customHTML"}
+	)
+
+	outputs, err := createSiteOutputFormats(output.Formats{customRSS, customHTML}, cfg)
+	assert.NoError(err)
+	assert.Equal(output.Formats{customHTML, customRSS}, outputs[KindHome])
 }
--- a/output/outputFormat.go
+++ b/output/outputFormat.go
@@ -140,6 +140,14 @@
 		NoUgly:    true,
 		Rel:       "alternate",
 	}
+
+	SitemapFormat = Format{
+		Name:      "Sitemap",
+		MediaType: media.XMLType,
+		BaseName:  "sitemap",
+		NoUgly:    true,
+		Rel:       "sitemap",
+	}
 )
 
 var DefaultFormats = Formats{
@@ -149,7 +157,9 @@
 	CSVFormat,
 	HTMLFormat,
 	JSONFormat,
+	RobotsTxtFormat,
 	RSSFormat,
+	SitemapFormat,
 }
 
 func init() {