summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hugolib/page_test.go60
-rw-r--r--hugolib/path_separators_test.go33
-rw-r--r--hugolib/site_output_test.go1
-rw-r--r--output/layout.go61
-rw-r--r--output/layout_test.go73
5 files changed, 95 insertions, 133 deletions
diff --git a/hugolib/page_test.go b/hugolib/page_test.go
index 82d6cbc8f..e7a26905d 100644
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -659,7 +659,11 @@ func TestCreateNewPage(t *testing.T) {
checkPageContent(t, p, normalizeExpected(ext, "<p>Simple Page</p>\n"))
checkPageSummary(t, p, "Simple Page")
checkPageType(t, p, "page")
- checkPageLayout(t, p, "page/single.html", "_default/single.html", "theme/page/single.html", "theme/_default/single.html")
+ checkPageLayout(t, p,
+ "page/single.html.html", "page/single.html",
+ "_default/single.html.html", "_default/single.html",
+ "theme/page/single.html.html", "theme/page/single.html",
+ "theme/_default/single.html.html", "theme/_default/single.html")
checkTruncation(t, p, false, "simple short page")
}
@@ -729,7 +733,6 @@ func TestPageWithDelimiter(t *testing.T) {
checkPageContent(t, p, normalizeExpected(ext, "<p>Summary Next Line</p>\n\n<p>Some more text</p>\n"), ext)
checkPageSummary(t, p, normalizeExpected(ext, "<p>Summary Next Line</p>"), ext)
checkPageType(t, p, "page")
- checkPageLayout(t, p, "page/single.html", "_default/single.html", "theme/page/single.html", "theme/_default/single.html")
checkTruncation(t, p, true, "page with summary delimiter")
}
@@ -787,7 +790,6 @@ func TestPageWithShortCodeInSummary(t *testing.T) {
checkPageContent(t, p, normalizeExpected(ext, "<p>Summary Next Line. \n<figure >\n \n <img src=\"/not/real\" />\n \n \n</figure>\n.\nMore text here.</p>\n\n<p>Some more text</p>\n"))
checkPageSummary(t, p, "Summary Next Line. . More text here. Some more text")
checkPageType(t, p, "page")
- checkPageLayout(t, p, "page/single.html", "_default/single.html", "theme/page/single.html", "theme/_default/single.html")
}
testAllMarkdownEnginesForPages(t, assertFunc, nil, simplePageWithShortcodeInSummary)
@@ -846,7 +848,6 @@ func TestPageWithMoreTag(t *testing.T) {
checkPageContent(t, p, normalizeExpected(ext, "<p>Summary Same Line</p>\n\n<p>Some more text</p>\n"))
checkPageSummary(t, p, normalizeExpected(ext, "<p>Summary Same Line</p>"))
checkPageType(t, p, "page")
- checkPageLayout(t, p, "page/single.html", "_default/single.html", "theme/page/single.html", "theme/_default/single.html")
}
@@ -1103,57 +1104,6 @@ func L(s ...string) []string {
return s
}
-func TestLayoutOverride(t *testing.T) {
- t.Parallel()
- var (
- pathContentTwoDir = filepath.Join("content", "dub", "sub", "file1.md")
- pathContentOneDir = filepath.Join("content", "gub", "file1.md")
- pathContentNoDir = filepath.Join("content", "file1")
- pathOneDirectory = filepath.Join("fub", "file1.md")
- pathNoDirectory = filepath.Join("file1.md")
- )
- tests := []struct {
- content string
- path string
- expectedLayout []string
- }{
- {simplePageNoLayout, pathContentTwoDir, L("dub/single.html", "_default/single.html")},
- {simplePageNoLayout, pathContentOneDir, L("gub/single.html", "_default/single.html")},
- {simplePageNoLayout, pathContentNoDir, L("page/single.html", "_default/single.html")},
- {simplePageNoLayout, pathOneDirectory, L("fub/single.html", "_default/single.html")},
- {simplePageNoLayout, pathNoDirectory, L("page/single.html", "_default/single.html")},
- {simplePageLayoutFoobar, pathContentTwoDir, L("dub/foobar.html", "_default/foobar.html")},
- {simplePageLayoutFoobar, pathContentOneDir, L("gub/foobar.html", "_default/foobar.html")},
- {simplePageLayoutFoobar, pathOneDirectory, L("fub/foobar.html", "_default/foobar.html")},
- {simplePageLayoutFoobar, pathNoDirectory, L("page/foobar.html", "_default/foobar.html")},
- {simplePageTypeFoobar, pathContentTwoDir, L("foobar/single.html", "_default/single.html")},
- {simplePageTypeFoobar, pathContentOneDir, L("foobar/single.html", "_default/single.html")},
- {simplePageTypeFoobar, pathContentNoDir, L("foobar/single.html", "_default/single.html")},
- {simplePageTypeFoobar, pathOneDirectory, L("foobar/single.html", "_default/single.html")},
- {simplePageTypeFoobar, pathNoDirectory, L("foobar/single.html", "_default/single.html")},
- {simplePageTypeLayout, pathContentTwoDir, L("barfoo/buzfoo.html", "_default/buzfoo.html")},
- {simplePageTypeLayout, pathContentOneDir, L("barfoo/buzfoo.html", "_default/buzfoo.html")},
- {simplePageTypeLayout, pathContentNoDir, L("barfoo/buzfoo.html", "_default/buzfoo.html")},
- {simplePageTypeLayout, pathOneDirectory, L("barfoo/buzfoo.html", "_default/buzfoo.html")},
- {simplePageTypeLayout, pathNoDirectory, L("barfoo/buzfoo.html", "_default/buzfoo.html")},
- }
- for _, test := range tests {
- s := newTestSite(t)
- p, _ := s.NewPage(test.path)
- _, err := p.ReadFrom(strings.NewReader(test.content))
- if err != nil {
- t.Fatalf("Unable to parse content:\n%s\n", test.content)
- }
-
- for _, y := range test.expectedLayout {
- test.expectedLayout = append(test.expectedLayout, "theme/"+y)
- }
- if !listEqual(p.layouts(), test.expectedLayout) {
- t.Errorf("Layout mismatch. Expected: %s, got: %s", test.expectedLayout, p.layouts())
- }
- }
-}
-
func TestSliceToLower(t *testing.T) {
t.Parallel()
tests := []struct {
diff --git a/hugolib/path_separators_test.go b/hugolib/path_separators_test.go
index bc1bcec0d..3a73869ad 100644
--- a/hugolib/path_separators_test.go
+++ b/hugolib/path_separators_test.go
@@ -36,36 +36,3 @@ func TestDegenerateMissingFolderInPageFilename(t *testing.T) {
t.Fatalf("No section should be set for a file path: foobar")
}
}
-
-func TestNewPageWithFilePath(t *testing.T) {
- t.Parallel()
- s := newTestSite(t)
- toCheck := []struct {
- input string
- section string
- layout []string
- }{
- {filepath.Join("sub", "foobar.html"), "sub", L("sub/single.html", "_default/single.html")},
- {filepath.Join("content", "foobar.html"), "", L("page/single.html", "_default/single.html")},
- {filepath.Join("content", "sub", "foobar.html"), "sub", L("sub/single.html", "_default/single.html")},
- {filepath.Join("content", "dub", "sub", "foobar.html"), "dub", L("dub/single.html", "_default/single.html")},
- }
-
- for i, el := range toCheck {
- p, err := s.NewPageFrom(strings.NewReader(simplePageYAML), el.input)
- if err != nil {
- t.Errorf("[%d] Reading from simplePageYAML resulted in an error: %s", i, err)
- }
- if p.Section() != el.section {
- t.Errorf("[%d] Section incorrect page %s. got %s but expected %s", i, el.input, p.Section(), el.section)
- }
-
- for _, y := range el.layout {
- el.layout = append(el.layout, "theme/"+y)
- }
-
- if !listEqual(p.layouts(), el.layout) {
- t.Errorf("[%d] Layout incorrect. got '%s' but expected '%s'", i, p.layouts(), el.layout)
- }
- }
-}
diff --git a/hugolib/site_output_test.go b/hugolib/site_output_test.go
index e67818fb1..c449c6541 100644
--- a/hugolib/site_output_test.go
+++ b/hugolib/site_output_test.go
@@ -21,6 +21,7 @@ import (
)
func TestDefaultOutputDefinitions(t *testing.T) {
+ t.Parallel()
defs := defaultOutputDefinitions
tests := []struct {
diff --git a/output/layout.go b/output/layout.go
index 0e0f33dad..1d2cbeed0 100644
--- a/output/layout.go
+++ b/output/layout.go
@@ -37,12 +37,27 @@ func NewLayoutHandler(hasTheme bool) *LayoutHandler {
return &LayoutHandler{hasTheme: hasTheme}
}
-// TODO(bep) output theme layouts
-var (
- layoutsHome = "index.html _default/list.html"
- layoutsSection = "section/SECTION.html SECTION/list.html _default/section.html _default/list.html indexes/SECTION.html _default/indexes.html"
- layoutTaxonomy = "taxonomy/SECTION.html indexes/SECTION.html _default/taxonomy.html _default/list.html"
- layoutTaxonomyTerm = "taxonomy/SECTION.terms.html _default/terms.html indexes/indexes.html"
+const (
+ layoutsHome = "index.NAME.SUFFIX index.SUFFIX _default/list.NAME.SUFFIX _default/list.SUFFIX"
+ layoutsSection = `
+section/SECTION.NAME.SUFFIX section/SECTION.SUFFIX
+SECTION/list.NAME.SUFFIX SECTION/list.SUFFIX
+_default/section.NAME.SUFFIX _default/section.SUFFIX
+_default/list.NAME.SUFFIX _default/list.SUFFIX
+indexes/SECTION.NAME.SUFFIX indexes/SECTION.SUFFIX
+_default/indexes.NAME.SUFFIX _default/indexes.SUFFIX
+`
+ layoutTaxonomy = `
+taxonomy/SECTION.NAME.SUFFIX taxonomy/SECTION.SUFFIX
+indexes/SECTION.NAME.SUFFIX indexes/SECTION.SUFFIX
+_default/taxonomy.NAME.SUFFIX _default/taxonomy.SUFFIX
+_default/list.NAME.SUFFIX _default/list.SUFFIX
+`
+ layoutTaxonomyTerm = `
+taxonomy/SECTION.terms.NAME.SUFFIX taxonomy/SECTION.terms.SUFFIX
+_default/terms.NAME.SUFFIX _default/terms.SUFFIX
+indexes/indexes.NAME.SUFFIX indexes/indexes.SUFFIX
+`
)
func (l *LayoutHandler) For(id LayoutIdentifier, layoutOverride string, tp Type) []string {
@@ -57,15 +72,15 @@ func (l *LayoutHandler) For(id LayoutIdentifier, layoutOverride string, tp Type)
switch id.PageKind() {
// TODO(bep) move the Kind constants some common place.
case "home":
- layouts = strings.Fields(layoutsHome)
+ layouts = resolveTemplate(layoutsHome, id, tp)
case "section":
- layouts = strings.Fields(strings.Replace(layoutsSection, "SECTION", id.PageSection(), -1))
+ layouts = resolveTemplate(layoutsSection, id, tp)
case "taxonomy":
- layouts = strings.Fields(strings.Replace(layoutTaxonomy, "SECTION", id.PageSection(), -1))
+ layouts = resolveTemplate(layoutTaxonomy, id, tp)
case "taxonomyTerm":
- layouts = strings.Fields(strings.Replace(layoutTaxonomyTerm, "SECTION", id.PageSection(), -1))
+ layouts = resolveTemplate(layoutTaxonomyTerm, id, tp)
case "page":
- layouts = regularPageLayouts(id.PageType(), layout)
+ layouts = regularPageLayouts(id.PageType(), layout, tp)
}
if l.hasTheme {
@@ -97,23 +112,41 @@ func (l *LayoutHandler) For(id LayoutIdentifier, layoutOverride string, tp Type)
return layouts
}
-func regularPageLayouts(types string, layout string) (layouts []string) {
+func resolveTemplate(templ string, id LayoutIdentifier, tp Type) []string {
+ return strings.Fields(replaceKeyValues(templ,
+ "SUFFIX", tp.MediaType.Suffix,
+ "NAME", strings.ToLower(tp.Name),
+ "SECTION", id.PageSection()))
+}
+
+func replaceKeyValues(s string, oldNew ...string) string {
+ replacer := strings.NewReplacer(oldNew...)
+ return replacer.Replace(s)
+}
+
+func regularPageLayouts(types string, layout string, tp Type) (layouts []string) {
if layout == "" {
layout = "single"
}
+ suffix := tp.MediaType.Suffix
+ name := strings.ToLower(tp.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.html", strings.ToLower(path.Join(search...)), layout))
+ 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.html", layout))
+ layouts = append(layouts, fmt.Sprintf("_default/%s.%s.%s", layout, name, suffix))
+ layouts = append(layouts, fmt.Sprintf("_default/%s.%s", layout, suffix))
return
}
diff --git a/output/layout_test.go b/output/layout_test.go
index 333216e17..8f851b895 100644
--- a/output/layout_test.go
+++ b/output/layout_test.go
@@ -14,9 +14,10 @@
package output
import (
- "fmt"
"testing"
+ "github.com/spf13/hugo/media"
+
"github.com/stretchr/testify/require"
)
@@ -43,46 +44,56 @@ func (l testLayoutIdentifier) PageSection() string {
return l.pageSection
}
+var ampType = Type{
+ Name: "AMP",
+ MediaType: media.HTMLType,
+ BaseName: "index",
+}
+
func TestLayout(t *testing.T) {
- for i, this := range []struct {
+ for _, this := range []struct {
+ name string
li testLayoutIdentifier
hasTheme bool
layoutOverride string
tp Type
expect []string
}{
- {testLayoutIdentifier{"home", "", "", ""}, true, "", HTMLType,
- []string{"index.html", "_default/list.html", "theme/index.html", "theme/_default/list.html"}},
- {testLayoutIdentifier{"section", "sect1", "", ""}, false, "", HTMLType,
- []string{"section/sect1.html", "sect1/list.html"}},
- {testLayoutIdentifier{"taxonomy", "tag", "", ""}, false, "", HTMLType,
- []string{"taxonomy/tag.html", "indexes/tag.html"}},
- {testLayoutIdentifier{"taxonomyTerm", "categories", "", ""}, false, "", HTMLType,
- []string{"taxonomy/categories.terms.html", "_default/terms.html"}},
- {testLayoutIdentifier{"page", "", "", ""}, true, "", HTMLType,
- []string{"_default/single.html", "theme/_default/single.html"}},
- {testLayoutIdentifier{"page", "", "mylayout", ""}, false, "", HTMLType,
- []string{"_default/mylayout.html"}},
- {testLayoutIdentifier{"page", "", "mylayout", "myttype"}, false, "", HTMLType,
- []string{"myttype/mylayout.html", "_default/mylayout.html"}},
- {testLayoutIdentifier{"page", "", "mylayout", "myttype/mysubtype"}, false, "", HTMLType,
- []string{"myttype/mysubtype/mylayout.html", "myttype/mylayout.html", "_default/mylayout.html"}},
- {testLayoutIdentifier{"page", "", "mylayout", "myttype"}, false, "myotherlayout", HTMLType,
- []string{"myttype/myotherlayout.html", "_default/myotherlayout.html"}},
+ {"Home", testLayoutIdentifier{"home", "", "", ""}, true, "", ampType,
+ []string{"index.amp.html", "index.html", "_default/list.amp.html", "_default/list.html", "theme/index.amp.html", "theme/index.html"}},
+ {"Section", testLayoutIdentifier{"section", "sect1", "", ""}, false, "", ampType,
+ []string{"section/sect1.amp.html", "section/sect1.html"}},
+ {"Taxonomy", testLayoutIdentifier{"taxonomy", "tag", "", ""}, false, "", ampType,
+ []string{"taxonomy/tag.amp.html", "taxonomy/tag.html"}},
+ {"Taxonomy term", testLayoutIdentifier{"taxonomyTerm", "categories", "", ""}, false, "", ampType,
+ []string{"taxonomy/categories.terms.amp.html", "taxonomy/categories.terms.html", "_default/terms.amp.html"}},
+ {"Page", testLayoutIdentifier{"page", "", "", ""}, true, "", ampType,
+ []string{"_default/single.amp.html", "_default/single.html", "theme/_default/single.amp.html"}},
+ {"Page with layout", testLayoutIdentifier{"page", "", "mylayout", ""}, false, "", ampType,
+ []string{"_default/mylayout.amp.html", "_default/mylayout.html"}},
+ {"Page with layout and type", testLayoutIdentifier{"page", "", "mylayout", "myttype"}, false, "", ampType,
+ []string{"myttype/mylayout.amp.html", "myttype/mylayout.html", "_default/mylayout.amp.html"}},
+ {"Page with layout and type with subtype", testLayoutIdentifier{"page", "", "mylayout", "myttype/mysubtype"}, false, "", ampType,
+ []string{"myttype/mysubtype/mylayout.amp.html", "myttype/mysubtype/mylayout.html", "myttype/mylayout.amp.html"}},
+ {"Page with overridden layout", testLayoutIdentifier{"page", "", "mylayout", "myttype"}, false, "myotherlayout", ampType,
+ []string{"myttype/myotherlayout.amp.html", "myttype/myotherlayout.html"}},
} {
- l := NewLayoutHandler(this.hasTheme)
- logMsg := fmt.Sprintf("Test %d", i)
- layouts := l.For(this.li, this.layoutOverride, this.tp)
- require.NotNil(t, layouts, logMsg)
- require.True(t, len(layouts) >= len(this.expect), logMsg)
- // Not checking the complete list for now ...
- require.Equal(t, this.expect, layouts[:len(this.expect)], logMsg)
+ t.Run(this.name, func(t *testing.T) {
+ l := NewLayoutHandler(this.hasTheme)
+
+ layouts := l.For(this.li, this.layoutOverride, this.tp)
+
+ require.NotNil(t, layouts)
+ require.True(t, len(layouts) >= len(this.expect))
+ // Not checking the complete list for now ...
+ require.Equal(t, this.expect, layouts[:len(this.expect)])
- if !this.hasTheme {
- for _, layout := range layouts {
- require.NotContains(t, layout, "theme", logMsg)
+ if !this.hasTheme {
+ for _, layout := range layouts {
+ require.NotContains(t, layout, "theme")
+ }
}
- }
+ })
}
}