From 6b76841b052b97625b8995f326d758b89f5c2349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Thu, 2 May 2019 09:54:26 +0200 Subject: [PATCH] output: Fix permalink in sitemap etc. when multiple permalinkable output formats 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 | 2 +- hugolib/sitemap_test.go | 19 +++++++++++++++++++ output/outputFormat.go | 25 ++++++++++++++++++++++--- output/outputFormat_test.go | 23 +++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/hugolib/site_render.go b/hugolib/site_render.go index 9ade951df..34f288da2 100644 --- a/hugolib/site_render.go +++ b/hugolib/site_render.go @@ -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 diff --git a/hugolib/sitemap_test.go b/hugolib/sitemap_test.go index cab13d356..5aba6f09d 100644 --- a/hugolib/sitemap_test.go +++ b/hugolib/sitemap_test.go @@ -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", " http://example.com/blog/html-amp/") +} diff --git a/output/outputFormat.go b/output/outputFormat.go index 9f371f856..c9c108ac5 100644 --- a/output/outputFormat.go +++ b/output/outputFormat.go @@ -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 diff --git a/output/outputFormat_test.go b/output/outputFormat_test.go index 6bd4dda5b..3d2fa5d17 100644 --- a/output/outputFormat_test.go +++ b/output/outputFormat_test.go @@ -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) + +}