Make the shortcode template lookup for output formats stable
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 23 Apr 2021 11:40:05 +0000 (13:40 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 23 Apr 2021 13:04:35 +0000 (15:04 +0200)
Fixes #7774

hugolib/shortcode_test.go
tpl/tplimpl/template.go

index bce95b527cdc653665b3205c6e15e958ac795d52..41f4eddb53cec745e9d3355b924f05e52d4af6e8 100644 (file)
@@ -1347,3 +1347,49 @@ title: "No Inner!"
        err := b.BuildE(BuildCfg{})
        b.Assert(err.Error(), qt.Contains, `failed to extract shortcode: shortcode "noinner" has no .Inner, yet a closing tag was provided`)
 }
+
+func TestShortcodeStableOutputFormatTemplates(t *testing.T) {
+       t.Parallel()
+
+       for i := 0; i < 5; i++ {
+
+               b := newTestSitesBuilder(t)
+
+               const numPages = 10
+
+               for i := 0; i < numPages; i++ {
+                       b.WithContent(fmt.Sprintf("page%d.md", i), `---
+title: "Page"
+outputs: ["html", "css", "csv", "json"]
+---
+{{< myshort >}}
+
+`)
+               }
+
+               b.WithTemplates(
+                       "_default/single.html", "{{ .Content }}",
+                       "_default/single.css", "{{ .Content }}",
+                       "_default/single.csv", "{{ .Content }}",
+                       "_default/single.json", "{{ .Content }}",
+                       "shortcodes/myshort.html", `Short-HTML`,
+                       "shortcodes/myshort.csv", `Short-CSV`,
+               )
+
+               b.Build(BuildCfg{})
+
+               //helpers.PrintFs(b.Fs.Destination, "public", os.Stdout)
+
+               for i := 0; i < numPages; i++ {
+                       b.AssertFileContent(fmt.Sprintf("public/page%d/index.html", i), "Short-HTML")
+                       b.AssertFileContent(fmt.Sprintf("public/page%d/index.csv", i), "Short-CSV")
+                       b.AssertFileContent(fmt.Sprintf("public/page%d/index.json", i), "Short-HTML")
+
+               }
+
+               for i := 0; i < numPages; i++ {
+                       b.AssertFileContent(fmt.Sprintf("public/page%d/styles.css", i), "Short-HTML")
+               }
+
+       }
+}
index 60e3b7df93febca85b307272d263451f5cffae17..75f25edac869c759c6f039f2ba430d619d0682d0 100644 (file)
@@ -19,6 +19,7 @@ import (
        "path/filepath"
        "reflect"
        "regexp"
+       "sort"
        "strings"
        "sync"
        "time"
@@ -814,6 +815,24 @@ func (t *templateHandler) postTransform() error {
                }
        }
 
+       for _, v := range t.shortcodes {
+               sort.Slice(v.variants, func(i, j int) bool {
+                       v1, v2 := v.variants[i], v.variants[j]
+                       name1, name2 := v1.ts.Name(), v2.ts.Name()
+                       isHTMl1, isHTML2 := strings.HasSuffix(name1, "html"), strings.HasSuffix(name2, "html")
+
+                       // There will be a weighted selection later, but make
+                       // sure these are sorted to get a stable selection for
+                       // output formats missing specific templates.
+                       // Prefer HTML.
+                       if isHTMl1 || isHTML2 && !(isHTMl1 && isHTML2) {
+                               return isHTMl1
+                       }
+
+                       return name1 < name2
+               })
+       }
+
        return nil
 }