output: Fix permalink in sitemap etc. when multiple permalinkable output formats
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 2 May 2019 07:54:26 +0000 (09:54 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 2 May 2019 12:23:16 +0000 (14:23 +0200)
In Hugo 0.55.0 we made AMP `permalinkable`. We also render the output formats in their natural sort order, meaning `AMP` will be rendered before `HTML`. References in the sitemap would then point to the AMP version, and this is normally not what you'd want.

This commit fixes that by making `HTML` by default sort before the others.

If this is not you want, you can set `weight` on the output format configuration.

Fixes #5910

hugolib/site_render.go
hugolib/sitemap_test.go
output/outputFormat.go
output/outputFormat_test.go

index 9ade951df1a510e9b07f67cea3030836e22ebfe0..34f288da231b8c83c40515c5283d986bd37c67bc 100644 (file)
@@ -35,7 +35,7 @@ type siteRenderContext struct {
        sitesOutIdx int
 
        // Zero based index of the output formats configured within a Site.
-       // Note that these outputs are sorted, so CSS will come before HTML.
+       // Note that these outputs are sorted.
        outIdx int
 
        multihost bool
index cab13d356bc1964885bdb844181ab62752cd7414..5aba6f09dd1dd3b963c2d38d457710ef223876bd 100644 (file)
@@ -100,3 +100,22 @@ func TestParseSitemap(t *testing.T) {
        }
 
 }
+
+// https://github.com/gohugoio/hugo/issues/5910
+func TestSitemapOutputFormats(t *testing.T) {
+
+       b := newTestSitesBuilder(t).WithSimpleConfigFile()
+
+       b.WithContent("blog/html-amp.md", `
+---
+Title: AMP and HTML
+outputs: [ "html", "amp" ]
+---
+
+`)
+
+       b.Build(BuildCfg{})
+
+       // Should link to the HTML version.
+       b.AssertFileContent("public/sitemap.xml", " <loc>http://example.com/blog/html-amp/</loc>")
+}
index 9f371f85652967800294c893c85a9eb011d8d422..c9c108ac5a2d18ee74df5c77eec0cb4b70f5f6a0 100644 (file)
@@ -78,6 +78,9 @@ type Format struct {
        // example. AMP would, however, be a good example of an output format where this
        // behaviour is wanted.
        Permalinkable bool `json:"permalinkable"`
+
+       // Setting this to a non-zero value will be used as the first sort criteria.
+       Weight int `json:"weight"`
 }
 
 // An ordered list of built-in output formats.
@@ -125,6 +128,10 @@ var (
                Rel:           "canonical",
                IsHTML:        true,
                Permalinkable: true,
+
+               // Weight will be used as first sort criteria. HTML will, by default,
+               // be rendered first, but set it to 10 so it's easy to put one above it.
+               Weight: 10,
        }
 
        JSONFormat = Format{
@@ -180,9 +187,21 @@ func init() {
 // Formats is a slice of Format.
 type Formats []Format
 
-func (formats Formats) Len() int           { return len(formats) }
-func (formats Formats) Swap(i, j int)      { formats[i], formats[j] = formats[j], formats[i] }
-func (formats Formats) Less(i, j int) bool { return formats[i].Name < formats[j].Name }
+func (formats Formats) Len() int      { return len(formats) }
+func (formats Formats) Swap(i, j int) { formats[i], formats[j] = formats[j], formats[i] }
+func (formats Formats) Less(i, j int) bool {
+       fi, fj := formats[i], formats[j]
+       if fi.Weight == fj.Weight {
+               return fi.Name < fj.Name
+       }
+
+       if fj.Weight == 0 {
+               return true
+       }
+
+       return fi.Weight > 0 && fi.Weight < fj.Weight
+
+}
 
 // GetBySuffix gets a output format given as suffix, e.g. "html".
 // It will return false if no format could be found, or if the suffix given
index 6bd4dda5b2caa5671379fc24c0b10b58bbe4acab..3d2fa5d1722897d649cf2e1c3fa270204e4ec229 100644 (file)
@@ -15,6 +15,7 @@ package output
 
 import (
        "fmt"
+       "sort"
        "testing"
 
        "github.com/gohugoio/hugo/media"
@@ -225,3 +226,25 @@ func TestDecodeFormats(t *testing.T) {
                }
        }
 }
+
+func TestSort(t *testing.T) {
+       assert := require.New(t)
+       assert.Equal("HTML", DefaultFormats[0].Name)
+       assert.Equal("AMP", DefaultFormats[1].Name)
+
+       json := JSONFormat
+       json.Weight = 1
+
+       formats := Formats{
+               AMPFormat,
+               HTMLFormat,
+               json,
+       }
+
+       sort.Sort(formats)
+
+       assert.Equal("JSON", formats[0].Name)
+       assert.Equal("HTML", formats[1].Name)
+       assert.Equal("AMP", formats[2].Name)
+
+}