URI: 
       Allow partial redefinition of the ouputs config - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit f8dc47eeffa847fd0b51e376da355e3d957848a6
   DIR parent ae3fa349de6daf1bbcd09ffc859d6b2e44764795
  HTML Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
       Date:   Sat, 10 Mar 2018 11:45:29 +0100
       
       Allow partial redefinition of the ouputs config
       
       Fixes #4487
       
       Diffstat:
         M hugolib/site_output.go              |      86 +++++++++++++++++--------------
         M hugolib/site_output_test.go         |     129 +++++++++++++++++++------------
         M output/outputFormat.go              |      10 ++++++++++
       
       3 files changed, 137 insertions(+), 88 deletions(-)
       ---
   DIR diff --git a/hugolib/site_output.go b/hugolib/site_output.go
       @@ -24,9 +24,46 @@ import (
                "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 @@ func createSiteOutputFormats(allFormats output.Formats, cfg config.Provider) (ma
                        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 @@ func createSiteOutputFormats(allFormats output.Formats, cfg config.Provider) (ma
                                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
       -}
   DIR diff --git 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 @@ import (
                "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) {
       @@ -373,3 +324,83 @@ baseName = "customdelimbase"
                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])
       +}
   DIR diff --git a/output/outputFormat.go b/output/outputFormat.go
       @@ -140,6 +140,14 @@ var (
                        NoUgly:    true,
                        Rel:       "alternate",
                }
       +
       +        SitemapFormat = Format{
       +                Name:      "Sitemap",
       +                MediaType: media.XMLType,
       +                BaseName:  "sitemap",
       +                NoUgly:    true,
       +                Rel:       "sitemap",
       +        }
        )
        
        var DefaultFormats = Formats{
       @@ -149,7 +157,9 @@ var DefaultFormats = Formats{
                CSVFormat,
                HTMLFormat,
                JSONFormat,
       +        RobotsTxtFormat,
                RSSFormat,
       +        SitemapFormat,
        }
        
        func init() {