summaryrefslogtreecommitdiffstats
path: root/output
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-01-13 17:21:42 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-01-14 19:59:51 +0100
commit51dd462c3958f7cf032b06503f1f200a6aceebb9 (patch)
tree6e153b1daa623729a7a469b996b15cf38ac5cf8e /output
parentb6ea6d07d0b072d850fb066c78976acd6c2f5e81 (diff)
layout: Respect Type and Layout for list template selection
This commit also has some other nice side-effects: * The layout logic is unified for all page types, which should make it less surprising * Page.Render now supports all types * The legacy "indexes" type is removed from the template lookup order. This is an undocumented type from early Hugo days. This means that having a template in, say, `/layouts/indexes/list.html` will no longer work. * The theme override logic is improved. As an example, an `index.html` in theme will now wn over a `_default/list.html` in the project, which most will expect. Fixes #3005 Fixes #3245
Diffstat (limited to 'output')
-rw-r--r--output/docshelper.go33
-rw-r--r--output/layout.go300
-rw-r--r--output/layout_test.go74
3 files changed, 210 insertions, 197 deletions
diff --git a/output/docshelper.go b/output/docshelper.go
index 9ed94b09b..5ccf0f57d 100644
--- a/output/docshelper.go
+++ b/output/docshelper.go
@@ -37,27 +37,26 @@ func createLayoutExamples() interface{} {
)
for _, example := range []struct {
- name string
- d LayoutDescriptor
- hasTheme bool
- layoutOverride string
- f Format
+ name string
+ d LayoutDescriptor
+ hasTheme bool
+ f Format
}{
- {`AMP home, with theme "demoTheme".`, LayoutDescriptor{Kind: "home"}, true, "", AMPFormat},
- {`AMP home, French language".`, LayoutDescriptor{Kind: "home", Lang: "fr"}, false, "", AMPFormat},
- {"RSS home, no theme.", LayoutDescriptor{Kind: "home"}, false, "", RSSFormat},
- {"JSON home, no theme.", LayoutDescriptor{Kind: "home"}, false, "", JSONFormat},
- {fmt.Sprintf(`CSV regular, "layout: %s" in front matter.`, demoLayout), LayoutDescriptor{Kind: "page", Layout: demoLayout}, false, "", CSVFormat},
- {fmt.Sprintf(`JSON regular, "type: %s" in front matter.`, demoType), LayoutDescriptor{Kind: "page", Type: demoType}, false, "", JSONFormat},
- {"HTML regular.", LayoutDescriptor{Kind: "page"}, false, "", HTMLFormat},
- {"AMP regular.", LayoutDescriptor{Kind: "page"}, false, "", AMPFormat},
- {"Calendar blog section.", LayoutDescriptor{Kind: "section", Section: "blog"}, false, "", CalendarFormat},
- {"Calendar taxonomy list.", LayoutDescriptor{Kind: "taxonomy", Section: "tag"}, false, "", CalendarFormat},
- {"Calendar taxonomy term.", LayoutDescriptor{Kind: "taxonomyTerm", Section: "tag"}, false, "", CalendarFormat},
+ {`AMP home, with theme "demoTheme".`, LayoutDescriptor{Kind: "home"}, true, AMPFormat},
+ {`AMP home, French language".`, LayoutDescriptor{Kind: "home", Lang: "fr"}, false, AMPFormat},
+ {"RSS home, no theme.", LayoutDescriptor{Kind: "home"}, false, RSSFormat},
+ {"JSON home, no theme.", LayoutDescriptor{Kind: "home"}, false, JSONFormat},
+ {fmt.Sprintf(`CSV regular, "layout: %s" in front matter.`, demoLayout), LayoutDescriptor{Kind: "page", Layout: demoLayout}, false, CSVFormat},
+ {fmt.Sprintf(`JSON regular, "type: %s" in front matter.`, demoType), LayoutDescriptor{Kind: "page", Type: demoType}, false, JSONFormat},
+ {"HTML regular.", LayoutDescriptor{Kind: "page"}, false, HTMLFormat},
+ {"AMP regular.", LayoutDescriptor{Kind: "page"}, false, AMPFormat},
+ {"Calendar blog section.", LayoutDescriptor{Kind: "section", Section: "blog"}, false, CalendarFormat},
+ {"Calendar taxonomy list.", LayoutDescriptor{Kind: "taxonomy", Section: "tag"}, false, CalendarFormat},
+ {"Calendar taxonomy term.", LayoutDescriptor{Kind: "taxonomyTerm", Section: "tag"}, false, CalendarFormat},
} {
l := NewLayoutHandler(example.hasTheme)
- layouts, _ := l.For(example.d, example.layoutOverride, example.f)
+ layouts, _ := l.For(example.d, example.f)
basicExamples = append(basicExamples, Example{
Example: example.name,
diff --git a/output/layout.go b/output/layout.go
index ee3305758..5ffc19130 100644
--- a/output/layout.go
+++ b/output/layout.go
@@ -15,11 +15,16 @@ package output
import (
"fmt"
- "path"
"strings"
"sync"
)
+// These may be used as content sections with potential conflicts. Avoid that.
+var reservedSections = map[string]bool{
+ "shortcodes": true,
+ "partials": true,
+}
+
// LayoutDescriptor describes how a layout should be chosen. This is
// typically built from a Page.
type LayoutDescriptor struct {
@@ -28,6 +33,8 @@ type LayoutDescriptor struct {
Kind string
Lang string
Layout string
+ // LayoutOverride indicates what we should only look for the above layout.
+ LayoutOverride bool
}
// LayoutHandler calculates the layout template to use to render a given output type.
@@ -39,9 +46,8 @@ type LayoutHandler struct {
}
type layoutCacheKey struct {
- d LayoutDescriptor
- layoutOverride string
- f Format
+ d LayoutDescriptor
+ f Format
}
// NewLayoutHandler creates a new LayoutHandler.
@@ -49,50 +55,12 @@ func NewLayoutHandler(hasTheme bool) *LayoutHandler {
return &LayoutHandler{hasTheme: hasTheme, cache: make(map[layoutCacheKey][]string)}
}
-// RSS:
-// Home:"rss.xml", "_default/rss.xml", "_internal/_default/rss.xml"
-// Section: "section/" + section + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"
-// Taxonomy "taxonomy/" + singular + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"
-// Tax term: taxonomy/" + singular + ".terms.rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"
-
-const (
-
- // TODO(bep) variations reduce to 1 "."
-
- // The RSS templates doesn't map easily into the regular pages.
- layoutsRSSHome = `VARIATIONS _default/VARIATIONS _internal/_default/rss.xml`
- layoutsRSSSection = `section/SECTION.VARIATIONS _default/VARIATIONS VARIATIONS _internal/_default/rss.xml`
- layoutsRSSTaxonomy = `taxonomy/SECTION.VARIATIONS _default/VARIATIONS VARIATIONS _internal/_default/rss.xml`
- layoutsRSSTaxonomyTerm = `taxonomy/SECTION.terms.VARIATIONS _default/VARIATIONS VARIATIONS _internal/_default/rss.xml`
-
- layoutsHome = "index.VARIATIONS _default/list.VARIATIONS"
- layoutsSection = `
-section/SECTION.VARIATIONS
-SECTION/list.VARIATIONS
-_default/section.VARIATIONS
-_default/list.VARIATIONS
-indexes/SECTION.VARIATIONS
-_default/indexes.VARIATIONS
-`
- layoutsTaxonomy = `
-taxonomy/SECTION.VARIATIONS
-indexes/SECTION.VARIATIONS
-_default/taxonomy.VARIATIONS
-_default/list.VARIATIONS
-`
- layoutsTaxonomyTerm = `
-taxonomy/SECTION.terms.VARIATIONS
-_default/terms.VARIATIONS
-indexes/indexes.VARIATIONS
-`
-)
-
// For returns a layout for the given LayoutDescriptor and options.
// Layouts are rendered and cached internally.
-func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format) ([]string, error) {
+func (l *LayoutHandler) For(d LayoutDescriptor, f Format) ([]string, error) {
// We will get lots of requests for the same layouts, so avoid recalculations.
- key := layoutCacheKey{d, layoutOverride, f}
+ key := layoutCacheKey{d, f}
l.mu.RLock()
if cacheVal, found := l.cache[key]; found {
l.mu.RUnlock()
@@ -100,53 +68,18 @@ func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format)
}
l.mu.RUnlock()
- var layouts []string
-
- if layoutOverride != "" && d.Kind != "page" {
- return layouts, fmt.Errorf("Custom layout (%q) only supported for regular pages, not kind %q", layoutOverride, d.Kind)
- }
-
- layout := d.Layout
-
- if layoutOverride != "" {
- layout = layoutOverride
- }
-
- isRSS := f.Name == RSSFormat.Name
-
- if d.Kind == "page" {
- if isRSS {
- return []string{}, nil
- }
- layouts = regularPageLayouts(d.Type, layout, f)
- } else {
- if isRSS {
- layouts = resolveListTemplate(d, f,
- layoutsRSSHome,
- layoutsRSSSection,
- layoutsRSSTaxonomy,
- layoutsRSSTaxonomyTerm)
- } else {
- layouts = resolveListTemplate(d, f,
- layoutsHome,
- layoutsSection,
- layoutsTaxonomy,
- layoutsTaxonomyTerm)
- }
- }
+ layouts := resolvePageTemplate(d, f)
if l.hasTheme {
+ // From Hugo 0.33 we interleave the project/theme templates. This was kind of a fundamental change, but the
+ // previous behaviour was surprising.
+ // As an example, an `index.html` in theme for the home page will now win over a `_default/list.html` in the project.
layoutsWithThemeLayouts := []string{}
+
// First place all non internal templates
for _, t := range layouts {
if !strings.HasPrefix(t, "_internal/") {
layoutsWithThemeLayouts = append(layoutsWithThemeLayouts, t)
- }
- }
-
- // Then place theme templates with the same names
- for _, t := range layouts {
- if !strings.HasPrefix(t, "_internal/") {
layoutsWithThemeLayouts = append(layoutsWithThemeLayouts, "theme/"+t)
}
}
@@ -170,70 +103,167 @@ func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format)
return layouts, nil
}
-func resolveListTemplate(d LayoutDescriptor, f Format,
- homeLayouts,
- sectionLayouts,
- taxonomyLayouts,
- taxonomyTermLayouts string) []string {
- var layouts []string
+type layoutBuilder struct {
+ layoutVariations []string
+ typeVariations []string
+ d LayoutDescriptor
+ f Format
+}
+
+func (l *layoutBuilder) addLayoutVariations(vars ...string) {
+ for _, layoutVar := range vars {
+ if l.d.LayoutOverride && layoutVar != l.d.Layout {
+ continue
+ }
+ l.layoutVariations = append(l.layoutVariations, layoutVar)
+ }
+}
+
+func (l *layoutBuilder) addTypeVariations(vars ...string) {
+ for _, typeVar := range vars {
+ if !reservedSections[typeVar] {
+ l.typeVariations = append(l.typeVariations, typeVar)
+ }
+ }
+}
+
+func (l *layoutBuilder) addSectionType() {
+ if l.d.Section != "" {
+ l.addTypeVariations(l.d.Section)
+ }
+}
+
+func (l *layoutBuilder) addKind() {
+ l.addLayoutVariations(l.d.Kind)
+ l.addTypeVariations(l.d.Kind)
+}
+
+func resolvePageTemplate(d LayoutDescriptor, f Format) []string {
+
+ b := &layoutBuilder{d: d, f: f}
+
+ if d.Layout != "" {
+ b.addLayoutVariations(d.Layout)
+ }
+
+ if d.Type != "" {
+ b.addTypeVariations(d.Type)
+ }
switch d.Kind {
+ case "page":
+ b.addLayoutVariations("single")
+ b.addSectionType()
case "home":
- layouts = resolveTemplate(homeLayouts, d, f)
+ b.addLayoutVariations("index", "home")
+ // Also look in the root
+ b.addTypeVariations("")
case "section":
- layouts = resolveTemplate(sectionLayouts, d, f)
+ if d.Section != "" {
+ b.addLayoutVariations(d.Section)
+ }
+ b.addSectionType()
+ b.addKind()
case "taxonomy":
- layouts = resolveTemplate(taxonomyLayouts, d, f)
+ if d.Section != "" {
+ b.addLayoutVariations(d.Section)
+ }
+ b.addKind()
+ b.addSectionType()
+
case "taxonomyTerm":
- layouts = resolveTemplate(taxonomyTermLayouts, d, f)
- }
- return layouts
-}
+ if d.Section != "" {
+ b.addLayoutVariations(d.Section + ".terms")
+ }
+ b.addTypeVariations("taxonomy")
+ b.addSectionType()
+ b.addLayoutVariations("terms")
-func resolveTemplate(templ string, d LayoutDescriptor, f Format) []string {
+ }
- // VARIATIONS will be replaced with
- // .lang.name.suffix
- // .name.suffix
- // .lang.suffix
- // .suffix
- var replacementValues []string
+ isRSS := f.Name == RSSFormat.Name
+ if isRSS {
+ // The historic and common rss.xml case
+ b.addLayoutVariations("")
+ }
- name := strings.ToLower(f.Name)
+ // All have _default in their lookup path
+ b.addTypeVariations("_default")
- if d.Lang != "" {
- replacementValues = append(replacementValues, fmt.Sprintf("%s.%s.%s", d.Lang, name, f.MediaType.Suffix))
+ if d.Kind != "page" {
+ // Add the common list type
+ b.addLayoutVariations("list")
}
- replacementValues = append(replacementValues, fmt.Sprintf("%s.%s", name, f.MediaType.Suffix))
+ layouts := b.resolveVariations()
- if d.Lang != "" {
- replacementValues = append(replacementValues, fmt.Sprintf("%s.%s", d.Lang, f.MediaType.Suffix))
+ if isRSS {
+ layouts = append(layouts, "_internal/_default/rss.xml")
}
- isRSS := f.Name == RSSFormat.Name
+ return layouts
- if !isRSS {
- replacementValues = append(replacementValues, f.MediaType.Suffix)
- }
+}
+
+func (l *layoutBuilder) resolveVariations() []string {
var layouts []string
- templFields := strings.Fields(templ)
+ var variations []string
+ name := strings.ToLower(l.f.Name)
+
+ if l.d.Lang != "" {
+ // We prefer the most specific type before language.
+ variations = append(variations, []string{fmt.Sprintf("%s.%s", l.d.Lang, name), name, l.d.Lang}...)
+ } else {
+ variations = append(variations, name)
+ }
- for _, field := range templFields {
- for _, replacements := range replacementValues {
- layouts = append(layouts, replaceKeyValues(field, "VARIATIONS", replacements, "SECTION", d.Section))
+ variations = append(variations, "")
+
+ for _, typeVar := range l.typeVariations {
+ for _, variation := range variations {
+ for _, layoutVar := range l.layoutVariations {
+ if variation == "" && layoutVar == "" {
+ continue
+ }
+ template := layoutTemplate(typeVar, layoutVar)
+ layouts = append(layouts, replaceKeyValues(template,
+ "TYPE", typeVar,
+ "LAYOUT", layoutVar,
+ "VARIATIONS", variation,
+ "EXTENSION", l.f.MediaType.Suffix,
+ ))
+ }
}
+
}
return filterDotLess(layouts)
}
+func layoutTemplate(typeVar, layoutVar string) string {
+
+ var l string
+
+ if typeVar != "" {
+ l = "TYPE/"
+ }
+
+ if layoutVar != "" {
+ l += "LAYOUT.VARIATIONS.EXTENSION"
+ } else {
+ l += "VARIATIONS.EXTENSION"
+ }
+
+ return l
+}
+
func filterDotLess(layouts []string) []string {
var filteredLayouts []string
for _, l := range layouts {
+ l = strings.Replace(l, "..", ".", -1)
l = strings.Trim(l, ".")
// If media type has no suffix, we have "index" type of layouts in this list, which
// doesn't make much sense.
@@ -263,37 +293,3 @@ func replaceKeyValues(s string, oldNew ...string) string {
replacer := strings.NewReplacer(oldNew...)
return replacer.Replace(s)
}
-
-func regularPageLayouts(types string, layout string, f Format) []string {
- var layouts []string
-
- if layout == "" {
- layout = "single"
- }
-
- delimiter := "."
- if f.MediaType.Delimiter == "" {
- delimiter = ""
- }
-
- suffix := delimiter + f.MediaType.Suffix
- name := strings.ToLower(f.Name)
-
- if types != "" {
- t := strings.Split(types, "/")
-
- // Add type/layout.html
- for i := range t {
- search := t[:len(t)-i]
- layouts = append(layouts, fmt.Sprintf("%s/%s.%s%s", strings.ToLower(path.Join(search...)), layout, name, suffix))
- layouts = append(layouts, fmt.Sprintf("%s/%s%s", strings.ToLower(path.Join(search...)), layout, suffix))
-
- }
- }
-
- // Add _default/layout.html
- layouts = append(layouts, fmt.Sprintf("_default/%s.%s%s", layout, name, suffix))
- layouts = append(layouts, fmt.Sprintf("_default/%s%s", layout, suffix))
-
- return filterDotLess(layouts)
-}
diff --git a/output/layout_test.go b/output/layout_test.go
index 6fb958c9d..3c7fde41a 100644
--- a/output/layout_test.go
+++ b/output/layout_test.go
@@ -14,6 +14,9 @@
package output
import (
+ "fmt"
+ "reflect"
+ "strings"
"testing"
"github.com/gohugoio/hugo/media"
@@ -37,6 +40,8 @@ func TestLayout(t *testing.T) {
BaseName: "index",
}
+ htmlFormat = HTMLFormat
+
noExtDelimFormat = Format{
Name: "NEM",
MediaType: noExtNoDelimMediaType,
@@ -56,57 +61,74 @@ func TestLayout(t *testing.T) {
layoutOverride string
tp Format
expect []string
+ expectCount int
}{
{"Home", LayoutDescriptor{Kind: "home"}, true, "", ampType,
- []string{"index.amp.html", "index.html", "_default/list.amp.html", "_default/list.html", "theme/index.amp.html", "theme/index.html"}},
+ []string{"index.amp.html", "theme/index.amp.html", "home.amp.html", "theme/home.amp.html", "list.amp.html", "theme/list.amp.html", "index.html", "theme/index.html", "home.html", "theme/home.html", "list.html", "theme/list.html", "_default/index.amp.html"}, 24},
+ {"Home, HTML", LayoutDescriptor{Kind: "home"}, true, "", htmlFormat,
+ // We will eventually get to index.html. This looks stuttery, but makes the lookup logic easy to understand.
+ []string{"index.html.html", "theme/index.html.html", "home.html.html"}, 24},
{"Home, french language", LayoutDescriptor{Kind: "home", Lang: "fr"}, true, "", ampType,
- []string{"index.fr.amp.html", "index.amp.html", "index.fr.html", "index.html", "_default/list.fr.amp.html", "_default/list.amp.html", "_default/list.fr.html", "_default/list.html", "theme/index.fr.amp.html", "theme/index.amp.html", "theme/index.fr.html"}},
+ []string{"index.fr.amp.html", "theme/index.fr.amp.html"},
+ 48},
{"Home, no ext or delim", LayoutDescriptor{Kind: "home"}, true, "", noExtDelimFormat,
- []string{"index.nem", "_default/list.nem"}},
+ []string{"index.nem", "theme/index.nem", "home.nem", "theme/home.nem", "list.nem"}, 12},
{"Home, no ext", LayoutDescriptor{Kind: "home"}, true, "", noExt,
- []string{"index.nex", "_default/list.nex"}},
+ []string{"index.nex", "theme/index.nex", "home.nex", "theme/home.nex", "list.nex"}, 12},
{"Page, no ext or delim", LayoutDescriptor{Kind: "page"}, true, "", noExtDelimFormat,
- []string{"_default/single.nem", "theme/_default/single.nem"}},
+ []string{"_default/single.nem", "theme/_default/single.nem"}, 2},
{"Section", LayoutDescriptor{Kind: "section", Section: "sect1"}, false, "", ampType,
- []string{"section/sect1.amp.html", "section/sect1.html"}},
+ []string{"sect1/sect1.amp.html", "sect1/section.amp.html", "sect1/list.amp.html", "sect1/sect1.html", "sect1/section.html", "sect1/list.html", "section/sect1.amp.html", "section/section.amp.html"}, 18},
+ {"Section with layout", LayoutDescriptor{Kind: "section", Section: "sect1", Layout: "mylayout"}, false, "", ampType,
+ []string{"sect1/mylayout.amp.html", "sect1/sect1.amp.html", "sect1/section.amp.html", "sect1/list.amp.html", "sect1/mylayout.html", "sect1/sect1.html"}, 24},
{"Taxonomy", LayoutDescriptor{Kind: "taxonomy", Section: "tag"}, false, "", ampType,
- []string{"taxonomy/tag.amp.html", "taxonomy/tag.html"}},
+ []string{"taxonomy/tag.amp.html", "taxonomy/taxonomy.amp.html", "taxonomy/list.amp.html", "taxonomy/tag.html", "taxonomy/taxonomy.html"}, 18},
{"Taxonomy term", LayoutDescriptor{Kind: "taxonomyTerm", Section: "categories"}, false, "", ampType,
- []string{"taxonomy/categories.terms.amp.html", "taxonomy/categories.terms.html", "_default/terms.amp.html"}},
+ []string{"taxonomy/categories.terms.amp.html", "taxonomy/terms.amp.html", "taxonomy/list.amp.html", "taxonomy/categories.terms.html", "taxonomy/terms.html"}, 18},
{"Page", LayoutDescriptor{Kind: "page"}, true, "", ampType,
- []string{"_default/single.amp.html", "_default/single.html", "theme/_default/single.amp.html"}},
+ []string{"_default/single.amp.html", "theme/_default/single.amp.html", "_default/single.html", "theme/_default/single.html"}, 4},
{"Page with layout", LayoutDescriptor{Kind: "page", Layout: "mylayout"}, false, "", ampType,
- []string{"_default/mylayout.amp.html", "_default/mylayout.html"}},
+ []string{"_default/mylayout.amp.html", "_default/single.amp.html", "_default/mylayout.html", "_default/single.html"}, 4},
{"Page with layout and type", LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype"}, false, "", ampType,
- []string{"myttype/mylayout.amp.html", "myttype/mylayout.html", "_default/mylayout.amp.html"}},
+ []string{"myttype/mylayout.amp.html", "myttype/single.amp.html", "myttype/mylayout.html"}, 8},
{"Page with layout and type with subtype", LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype/mysubtype"}, false, "", ampType,
- []string{"myttype/mysubtype/mylayout.amp.html", "myttype/mysubtype/mylayout.html", "myttype/mylayout.amp.html"}},
- {"Page with overridden layout", LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype"}, false, "myotherlayout", ampType,
- []string{"myttype/myotherlayout.amp.html", "myttype/myotherlayout.html"}},
+ []string{"myttype/mysubtype/mylayout.amp.html", "myttype/mysubtype/single.amp.html", "myttype/mysubtype/mylayout.html"}, 8},
// RSS
{"RSS Home with theme", LayoutDescriptor{Kind: "home"}, true, "", RSSFormat,
- []string{"rss.xml", "_default/rss.xml", "theme/rss.xml", "theme/_default/rss.xml", "_internal/_default/rss.xml"}},
+ []string{"index.rss.xml", "theme/index.rss.xml", "home.rss.xml", "theme/home.rss.xml", "rss.xml"}, 29},
{"RSS Section", LayoutDescriptor{Kind: "section", Section: "sect1"}, false, "", RSSFormat,
- []string{"section/sect1.rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}},
+ []string{"sect1/sect1.rss.xml", "sect1/section.rss.xml", "sect1/rss.xml", "sect1/list.rss.xml", "sect1/sect1.xml", "sect1/section.xml"}, 22},
{"RSS Taxonomy", LayoutDescriptor{Kind: "taxonomy", Section: "tag"}, false, "", RSSFormat,
- []string{"taxonomy/tag.rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}},
+ []string{"taxonomy/tag.rss.xml", "taxonomy/taxonomy.rss.xml", "taxonomy/rss.xml", "taxonomy/list.rss.xml", "taxonomy/tag.xml", "taxonomy/taxonomy.xml"}, 22},
{"RSS Taxonomy term", LayoutDescriptor{Kind: "taxonomyTerm", Section: "tag"}, false, "", RSSFormat,
- []string{"taxonomy/tag.terms.rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}},
+ []string{"taxonomy/tag.terms.rss.xml", "taxonomy/terms.rss.xml", "taxonomy/rss.xml", "taxonomy/list.rss.xml", "taxonomy/tag.terms.xml"}, 22},
{"Home plain text", LayoutDescriptor{Kind: "home"}, true, "", JSONFormat,
- []string{"_text/index.json.json", "_text/index.json", "_text/_default/list.json.json", "_text/_default/list.json", "_text/theme/index.json.json", "_text/theme/index.json"}},
+ []string{"_text/index.json.json", "_text/theme/index.json.json", "_text/home.json.json", "_text/theme/home.json.json"}, 24},
{"Page plain text", LayoutDescriptor{Kind: "page"}, true, "", JSONFormat,
- []string{"_text/_default/single.json.json", "_text/_default/single.json", "_text/theme/_default/single.json.json"}},
+ []string{"_text/_default/single.json.json", "_text/theme/_default/single.json.json", "_text/_default/single.json", "_text/theme/_default/single.json"}, 4},
+ {"Reserved section, shortcodes", LayoutDescriptor{Kind: "section", Section: "shortcodes", Type: "shortcodes"}, true, "", ampType,
+ []string{"section/shortcodes.amp.html", "theme/section/shortcodes.amp.html"}, 24},
+ {"Reserved section, partials", LayoutDescriptor{Kind: "section", Section: "partials", Type: "partials"}, true, "", ampType,
+ []string{"section/partials.amp.html", "theme/section/partials.amp.html"}, 24},
} {
t.Run(this.name, func(t *testing.T) {
l := NewLayoutHandler(this.hasTheme)
- layouts, err := l.For(this.d, this.layoutOverride, this.tp)
+ layouts, err := l.For(this.d, this.tp)
require.NoError(t, err)
require.NotNil(t, layouts)
- require.True(t, len(layouts) >= len(this.expect))
+ require.True(t, len(layouts) >= len(this.expect), fmt.Sprint(layouts))
// Not checking the complete list for now ...
- require.Equal(t, this.expect, layouts[:len(this.expect)])
+ got := layouts[:len(this.expect)]
+ if len(layouts) != this.expectCount || !reflect.DeepEqual(got, this.expect) {
+ formatted := strings.Replace(fmt.Sprintf("%v", layouts), "[", "\"", 1)
+ formatted = strings.Replace(formatted, "]", "\"", 1)
+ formatted = strings.Replace(formatted, " ", "\", \"", -1)
+
+ t.Fatalf("Got %d/%d:\n%v\nExpected:\n%v\nAll:\n%v\nFormatted:\n%s", len(layouts), this.expectCount, got, this.expect, layouts, formatted)
+
+ }
if !this.hasTheme {
for _, layout := range layouts {
@@ -116,10 +138,6 @@ func TestLayout(t *testing.T) {
})
}
- l := NewLayoutHandler(false)
- _, err := l.For(LayoutDescriptor{Kind: "taxonomyTerm", Section: "tag"}, "override", RSSFormat)
- require.Error(t, err)
-
}
func BenchmarkLayout(b *testing.B) {
@@ -127,7 +145,7 @@ func BenchmarkLayout(b *testing.B) {
l := NewLayoutHandler(false)
for i := 0; i < b.N; i++ {
- layouts, err := l.For(descriptor, "", HTMLFormat)
+ layouts, err := l.For(descriptor, HTMLFormat)
require.NoError(b, err)
require.NotEmpty(b, layouts)
}