mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
hugolib: Use the new layout logic in Page
This commit is contained in:
parent
3bb52bf7bf
commit
10de077164
5 changed files with 88 additions and 78 deletions
109
hugolib/page.go
109
hugolib/page.go
|
@ -36,6 +36,8 @@ import (
|
|||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/spf13/hugo/output"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
bp "github.com/spf13/hugo/bufferpool"
|
||||
"github.com/spf13/hugo/media"
|
||||
|
@ -204,6 +206,43 @@ type Page struct {
|
|||
// The media types this page will be rendered to.
|
||||
// TODO(bep) probably wrap this to add additional information like template evaluation?
|
||||
mediaTypes media.Types
|
||||
|
||||
// Used to pick the correct template(s)
|
||||
layoutIdentifier pageLayoutIdentifier
|
||||
}
|
||||
|
||||
// Implements layout.LayoutIdentifier
|
||||
type pageLayoutIdentifier struct {
|
||||
*Page
|
||||
}
|
||||
|
||||
// PageKind returns the page's kind.
|
||||
func (p pageLayoutIdentifier) PageKind() string {
|
||||
return p.Kind
|
||||
}
|
||||
|
||||
// PageLayout returns the page's layout, if set.
|
||||
func (p pageLayoutIdentifier) PageLayout() string {
|
||||
return p.Layout
|
||||
}
|
||||
|
||||
// PageType returns the page's type, if set.
|
||||
func (p pageLayoutIdentifier) PageType() string {
|
||||
return p.Type()
|
||||
}
|
||||
|
||||
// PageType returns the page's section in layout terms.
|
||||
// This will be empty for regular pages, the section for section pages,
|
||||
// and the singular term for taxonomy and taxonomy terms pages.
|
||||
func (p pageLayoutIdentifier) PageSection() string {
|
||||
switch p.Kind {
|
||||
case KindSection:
|
||||
return p.sections[0]
|
||||
case KindTaxonomy, KindTaxonomyTerm:
|
||||
return p.s.taxonomiesPluralSingular[p.sections[0]]
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// pageInit lazy initializes different parts of the page. It is extracted
|
||||
|
@ -595,7 +634,7 @@ func (p *Page) getRenderingConfig() *helpers.Blackfriday {
|
|||
|
||||
func (s *Site) newPage(filename string) *Page {
|
||||
sp := source.NewSourceSpec(s.Cfg, s.Fs)
|
||||
page := Page{
|
||||
p := &Page{
|
||||
pageInit: &pageInit{},
|
||||
Kind: kindFromFilename(filename),
|
||||
contentType: "",
|
||||
|
@ -607,9 +646,10 @@ func (s *Site) newPage(filename string) *Page {
|
|||
Site: &s.Info,
|
||||
s: s,
|
||||
}
|
||||
p.layoutIdentifier = pageLayoutIdentifier{p}
|
||||
|
||||
s.Log.DEBUG.Println("Reading from", page.File.Path())
|
||||
return &page
|
||||
s.Log.DEBUG.Println("Reading from", p.File.Path())
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Page) IsRenderable() bool {
|
||||
|
@ -635,44 +675,23 @@ func (p *Page) Section() string {
|
|||
return p.Source.Section()
|
||||
}
|
||||
|
||||
func (p *Page) layouts(l ...string) []string {
|
||||
func (p *Page) layouts(layouts ...string) []string {
|
||||
if len(p.layoutsCalculated) > 0 {
|
||||
return p.layoutsCalculated
|
||||
}
|
||||
|
||||
switch p.Kind {
|
||||
case KindHome:
|
||||
return p.s.appendThemeTemplates([]string{"index.html", "_default/list.html"})
|
||||
case KindSection:
|
||||
section := p.sections[0]
|
||||
return p.s.appendThemeTemplates([]string{"section/" + section + ".html", section + "/list.html", "_default/section.html", "_default/list.html", "indexes/" + section + ".html", "_default/indexes.html"})
|
||||
case KindTaxonomy:
|
||||
singular := p.s.taxonomiesPluralSingular[p.sections[0]]
|
||||
return p.s.appendThemeTemplates([]string{"taxonomy/" + singular + ".html", "indexes/" + singular + ".html", "_default/taxonomy.html", "_default/list.html"})
|
||||
case KindTaxonomyTerm:
|
||||
singular := p.s.taxonomiesPluralSingular[p.sections[0]]
|
||||
return p.s.appendThemeTemplates([]string{"taxonomy/" + singular + ".terms.html", "_default/terms.html", "indexes/indexes.html"})
|
||||
layoutOverride := ""
|
||||
if len(layouts) > 0 {
|
||||
layoutOverride = layouts[0]
|
||||
}
|
||||
|
||||
// Regular Page handled below
|
||||
|
||||
if p.Layout != "" {
|
||||
return layouts(p.Type(), p.Layout)
|
||||
}
|
||||
|
||||
layout := ""
|
||||
if len(l) == 0 {
|
||||
layout = "single"
|
||||
} else {
|
||||
layout = l[0]
|
||||
}
|
||||
|
||||
return layouts(p.Type(), layout)
|
||||
return p.s.layoutHandler.For(p.layoutIdentifier, layoutOverride, output.HTMLType)
|
||||
}
|
||||
|
||||
// TODO(bep) consolidate and test these KindHome switches (see other layouts methods)s
|
||||
// rssLayouts returns RSS layouts to use for the RSS version of this page, nil
|
||||
// if no RSS should be rendered.
|
||||
// TODO(bep) output
|
||||
func (p *Page) rssLayouts() []string {
|
||||
switch p.Kind {
|
||||
case KindHome:
|
||||
|
@ -693,26 +712,6 @@ func (p *Page) rssLayouts() []string {
|
|||
return nil
|
||||
}
|
||||
|
||||
func layouts(types string, layout string) (layouts []string) {
|
||||
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))
|
||||
}
|
||||
|
||||
// Add _default/layout.html
|
||||
layouts = append(layouts, fmt.Sprintf("_default/%s.html", layout))
|
||||
|
||||
// Add theme/type/layout.html & theme/_default/layout.html
|
||||
for _, l := range layouts {
|
||||
layouts = append(layouts, "theme/"+l)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Site) NewPageFrom(buf io.Reader, name string) (*Page, error) {
|
||||
p, err := s.NewPage(name)
|
||||
if err != nil {
|
||||
|
@ -1360,14 +1359,8 @@ func (p *Page) Menus() PageMenus {
|
|||
return p.pageMenus
|
||||
}
|
||||
|
||||
func (p *Page) Render(layout ...string) template.HTML {
|
||||
var l []string
|
||||
|
||||
if len(layout) > 0 {
|
||||
l = layouts(p.Type(), layout[0])
|
||||
} else {
|
||||
l = p.layouts()
|
||||
}
|
||||
func (p *Page) Render(layouts ...string) template.HTML {
|
||||
l := p.layouts(layouts...)
|
||||
|
||||
return p.s.Tmpl.ExecuteTemplateToHTML(p, l...)
|
||||
}
|
||||
|
|
|
@ -1412,6 +1412,7 @@ func TestPageSimpleMethods(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestIndexPageSimpleMethods(t *testing.T) {
|
||||
s := newTestSite(t)
|
||||
t.Parallel()
|
||||
for i, this := range []struct {
|
||||
assertFunc func(n *Page) bool
|
||||
|
@ -1422,9 +1423,10 @@ func TestIndexPageSimpleMethods(t *testing.T) {
|
|||
{func(n *Page) bool { return n.Scratch() != nil }},
|
||||
{func(n *Page) bool { return n.Hugo() != nil }},
|
||||
{func(n *Page) bool { return n.Now().Unix() == time.Now().Unix() }},
|
||||
{func(n *Page) bool { return n.layoutIdentifier.Kind == KindHome }},
|
||||
} {
|
||||
|
||||
n := &Page{pageInit: &pageInit{}, Kind: KindHome}
|
||||
n := s.newHomePage()
|
||||
|
||||
n.RSSLink = "rssLink"
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import (
|
|||
bp "github.com/spf13/hugo/bufferpool"
|
||||
"github.com/spf13/hugo/deps"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/output"
|
||||
"github.com/spf13/hugo/parser"
|
||||
"github.com/spf13/hugo/source"
|
||||
"github.com/spf13/hugo/tpl"
|
||||
|
@ -100,6 +101,8 @@ type Site struct {
|
|||
// This is not a pointer by design.
|
||||
w siteWriter
|
||||
|
||||
layoutHandler *output.LayoutHandler
|
||||
|
||||
draftCount int
|
||||
futureCount int
|
||||
expiredCount int
|
||||
|
@ -121,7 +124,7 @@ func (s *Site) isEnabled(kind string) bool {
|
|||
|
||||
// reset returns a new Site prepared for rebuild.
|
||||
func (s *Site) reset() *Site {
|
||||
return &Site{Deps: s.Deps, disabledKinds: s.disabledKinds, Language: s.Language, owner: s.owner, PageCollections: newPageCollections()}
|
||||
return &Site{Deps: s.Deps, layoutHandler: &output.LayoutHandler{}, disabledKinds: s.disabledKinds, Language: s.Language, owner: s.owner, PageCollections: newPageCollections()}
|
||||
}
|
||||
|
||||
// newSite creates a new site with the given configuration.
|
||||
|
@ -137,7 +140,7 @@ func newSite(cfg deps.DepsCfg) (*Site, error) {
|
|||
disabledKinds[disabled] = true
|
||||
}
|
||||
|
||||
s := &Site{PageCollections: c, Language: cfg.Language, disabledKinds: disabledKinds}
|
||||
s := &Site{PageCollections: c, layoutHandler: &output.LayoutHandler{}, Language: cfg.Language, disabledKinds: disabledKinds}
|
||||
|
||||
s.Info = newSiteInfo(siteBuilderCfg{s: s, pageCollections: c, language: s.Language})
|
||||
|
||||
|
@ -2038,13 +2041,16 @@ func getGoMaxProcs() int {
|
|||
}
|
||||
|
||||
func (s *Site) newNodePage(typ string) *Page {
|
||||
return &Page{
|
||||
p := &Page{
|
||||
language: s.Language,
|
||||
pageInit: &pageInit{},
|
||||
Kind: typ,
|
||||
Data: make(map[string]interface{}),
|
||||
Site: &s.Info,
|
||||
s: s}
|
||||
p.layoutIdentifier = pageLayoutIdentifier{p}
|
||||
return p
|
||||
|
||||
}
|
||||
|
||||
func (s *Site) newHomePage() *Page {
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// LayoutIdentifier is used to pick the correct layout for a piece of content.
|
||||
type LayoutIdentifier interface {
|
||||
PageType() string
|
||||
PageSection() string // TODO(bep) name
|
||||
|
@ -28,7 +29,7 @@ type LayoutIdentifier interface {
|
|||
|
||||
// Layout calculates the layout template to use to render a given output type.
|
||||
// TODO(bep) output improve names
|
||||
type Layout struct {
|
||||
type LayoutHandler struct {
|
||||
}
|
||||
|
||||
// TODO(bep) output theme layouts
|
||||
|
@ -39,9 +40,15 @@ var (
|
|||
layoutTaxonomyTerm = "taxonomy/SECTION.terms.html _default/terms.html indexes/indexes.html"
|
||||
)
|
||||
|
||||
func (l *Layout) For(id LayoutIdentifier, tp Type) []string {
|
||||
func (l *LayoutHandler) For(id LayoutIdentifier, layoutOverride string, tp Type) []string {
|
||||
var layouts []string
|
||||
|
||||
layout := id.PageLayout()
|
||||
|
||||
if layoutOverride != "" {
|
||||
layout = layoutOverride
|
||||
}
|
||||
|
||||
switch id.PageKind() {
|
||||
// TODO(bep) move the Kind constants some common place.
|
||||
case "home":
|
||||
|
@ -53,7 +60,7 @@ func (l *Layout) For(id LayoutIdentifier, tp Type) []string {
|
|||
case "taxonomyTerm":
|
||||
layouts = strings.Fields(strings.Replace(layoutTaxonomyTerm, "SECTION", id.PageSection(), -1))
|
||||
case "page":
|
||||
layouts = regularPageLayouts(id.PageType(), id.PageLayout())
|
||||
layouts = regularPageLayouts(id.PageType(), layout)
|
||||
}
|
||||
|
||||
for _, l := range layouts {
|
||||
|
|
|
@ -43,23 +43,25 @@ func (l testLayoutIdentifier) PageSection() string {
|
|||
}
|
||||
|
||||
func TestLayout(t *testing.T) {
|
||||
l := &Layout{}
|
||||
l := &LayoutHandler{}
|
||||
|
||||
for _, this := range []struct {
|
||||
li testLayoutIdentifier
|
||||
tp Type
|
||||
expect []string
|
||||
li testLayoutIdentifier
|
||||
layoutOverride string
|
||||
tp Type
|
||||
expect []string
|
||||
}{
|
||||
{testLayoutIdentifier{"home", "", "", ""}, HTMLType, []string{"index.html", "_default/list.html", "theme/index.html", "theme/_default/list.html"}},
|
||||
{testLayoutIdentifier{"section", "sect1", "", ""}, HTMLType, []string{"section/sect1.html", "sect1/list.html"}},
|
||||
{testLayoutIdentifier{"taxonomy", "tag", "", ""}, HTMLType, []string{"taxonomy/tag.html", "indexes/tag.html"}},
|
||||
{testLayoutIdentifier{"taxonomyTerm", "categories", "", ""}, HTMLType, []string{"taxonomy/categories.terms.html", "_default/terms.html"}},
|
||||
{testLayoutIdentifier{"page", "", "", ""}, HTMLType, []string{"_default/single.html", "theme/_default/single.html"}},
|
||||
{testLayoutIdentifier{"page", "", "mylayout", ""}, HTMLType, []string{"_default/mylayout.html"}},
|
||||
{testLayoutIdentifier{"page", "", "mylayout", "myttype"}, HTMLType, []string{"myttype/mylayout.html", "_default/mylayout.html"}},
|
||||
{testLayoutIdentifier{"page", "", "mylayout", "myttype/mysubtype"}, HTMLType, []string{"myttype/mysubtype/mylayout.html", "myttype/mylayout.html", "_default/mylayout.html"}},
|
||||
{testLayoutIdentifier{"home", "", "", ""}, "", HTMLType, []string{"index.html", "_default/list.html", "theme/index.html", "theme/_default/list.html"}},
|
||||
{testLayoutIdentifier{"section", "sect1", "", ""}, "", HTMLType, []string{"section/sect1.html", "sect1/list.html"}},
|
||||
{testLayoutIdentifier{"taxonomy", "tag", "", ""}, "", HTMLType, []string{"taxonomy/tag.html", "indexes/tag.html"}},
|
||||
{testLayoutIdentifier{"taxonomyTerm", "categories", "", ""}, "", HTMLType, []string{"taxonomy/categories.terms.html", "_default/terms.html"}},
|
||||
{testLayoutIdentifier{"page", "", "", ""}, "", HTMLType, []string{"_default/single.html", "theme/_default/single.html"}},
|
||||
{testLayoutIdentifier{"page", "", "mylayout", ""}, "", HTMLType, []string{"_default/mylayout.html"}},
|
||||
{testLayoutIdentifier{"page", "", "mylayout", "myttype"}, "", HTMLType, []string{"myttype/mylayout.html", "_default/mylayout.html"}},
|
||||
{testLayoutIdentifier{"page", "", "mylayout", "myttype/mysubtype"}, "", HTMLType, []string{"myttype/mysubtype/mylayout.html", "myttype/mylayout.html", "_default/mylayout.html"}},
|
||||
{testLayoutIdentifier{"page", "", "mylayout", "myttype"}, "myotherlayout", HTMLType, []string{"myttype/myotherlayout.html", "_default/myotherlayout.html"}},
|
||||
} {
|
||||
layouts := l.For(this.li, this.tp)
|
||||
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 ...
|
||||
|
|
Loading…
Reference in a new issue