From 3ec5fc35043639e7592819014180666b1a8e926b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 7 Mar 2017 17:26:22 +0100 Subject: [PATCH] hugolib, output: Incorporate suffix and type in layout resolve And remove some now superflous and hard to maintain tests. --- hugolib/page_test.go | 60 +++------------------------ hugolib/path_separators_test.go | 33 --------------- hugolib/site_output_test.go | 1 + output/layout.go | 61 ++++++++++++++++++++------- output/layout_test.go | 73 +++++++++++++++++++-------------- 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, "

Simple Page

\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, "

Summary Next Line

\n\n

Some more text

\n"), ext) checkPageSummary(t, p, normalizeExpected(ext, "

Summary Next Line

"), 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, "

Summary Next Line. \n

\n \n \n \n \n
\n.\nMore text here.

\n\n

Some more text

\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, "

Summary Same Line

\n\n

Some more text

\n")) checkPageSummary(t, p, normalizeExpected(ext, "

Summary Same Line

")) 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) - if !this.hasTheme { - for _, layout := range layouts { - require.NotContains(t, layout, "theme", logMsg) + 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") + } } - } + }) } }