mirror of
https://github.com/gohugoio/hugo.git
synced 2025-03-15 02:04:02 +00:00
hugolib, output: Restrict Render to regular Pages
Using it for list pages doesn't work and has potential weird side-effects. The user probably meant to range over .Site.ReqularPages, and that is now marked clearly in the log.
This commit is contained in:
parent
e49a2b83ad
commit
930a3df1b7
6 changed files with 50 additions and 16 deletions
|
@ -1721,3 +1721,11 @@ func (p *Page) setValuesForKind(s *Site) {
|
||||||
p.URLPath.URL = "/" + path.Join(p.sections...) + "/"
|
p.URLPath.URL = "/" + path.Join(p.sections...) + "/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used in error logs.
|
||||||
|
func (p *Page) pathOrTitle() string {
|
||||||
|
if p.Path() != "" {
|
||||||
|
return p.Path()
|
||||||
|
}
|
||||||
|
return p.Title
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/hugo/media"
|
"github.com/spf13/hugo/media"
|
||||||
|
|
||||||
|
"github.com/spf13/hugo/helpers"
|
||||||
"github.com/spf13/hugo/output"
|
"github.com/spf13/hugo/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -85,9 +86,9 @@ func (p *PageOutput) copy() *PageOutput {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PageOutput) layouts(layouts ...string) []string {
|
func (p *PageOutput) layouts(layouts ...string) ([]string, error) {
|
||||||
if len(layouts) == 0 && p.selfLayout != "" {
|
if len(layouts) == 0 && p.selfLayout != "" {
|
||||||
return []string{p.selfLayout}
|
return []string{p.selfLayout}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutOverride := ""
|
layoutOverride := ""
|
||||||
|
@ -106,7 +107,11 @@ func (p *PageOutput) Render(layout ...string) template.HTML {
|
||||||
return template.HTML("")
|
return template.HTML("")
|
||||||
}
|
}
|
||||||
|
|
||||||
l := p.layouts(layout...)
|
l, err := p.layouts(layout...)
|
||||||
|
if err != nil {
|
||||||
|
helpers.DistinctErrorLog.Printf("in .Render: Failed to resolve layout %q for page %q", layout, p.pathOrTitle())
|
||||||
|
return template.HTML("")
|
||||||
|
}
|
||||||
return p.s.Tmpl.ExecuteTemplateToHTML(p, l...)
|
return p.s.Tmpl.ExecuteTemplateToHTML(p, l...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +127,7 @@ func (p *Page) Render(layout ...string) template.HTML {
|
||||||
pageOutput, err := newPageOutput(p, true, outFormat)
|
pageOutput, err := newPageOutput(p, true, outFormat)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.s.Log.ERROR.Printf("Failed to create output page for type %q for page %q: %s", outFormat.Name, p, err)
|
p.s.Log.ERROR.Printf("Failed to create output page for type %q for page %q: %s", outFormat.Name, p.pathOrTitle(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +142,7 @@ func (p *Page) Render(layout ...string) template.HTML {
|
||||||
// for list pages.
|
// for list pages.
|
||||||
func (p *Page) checkRender() bool {
|
func (p *Page) checkRender() bool {
|
||||||
if p.Kind != KindPage {
|
if p.Kind != KindPage {
|
||||||
p.s.Log.ERROR.Printf(".Render only available for regular pages, not for %q of kind %q", p.Path(), p.Kind)
|
helpers.DistinctErrorLog.Printf(".Render only available for regular pages, not for of kind %q. You probably meant .Site.RegularPages and not.Site.Pages.", p.Kind)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -1668,7 +1668,7 @@ func (s *Site) kindFromSections(sections []string) string {
|
||||||
return KindSection
|
return KindSection
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) layouts(p *PageOutput) []string {
|
func (s *Site) layouts(p *PageOutput) ([]string, error) {
|
||||||
return s.layoutHandler.For(p.layoutDescriptor, "", p.outputFormat)
|
return s.layoutHandler.For(p.layoutDescriptor, "", p.outputFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,11 @@ func pageRenderer(s *Site, pages <-chan *Page, results chan<- error, wg *sync.Wa
|
||||||
if page.selfLayout != "" {
|
if page.selfLayout != "" {
|
||||||
layouts = []string{page.selfLayout}
|
layouts = []string{page.selfLayout}
|
||||||
} else {
|
} else {
|
||||||
layouts = s.layouts(pageOutput)
|
layouts, err = s.layouts(pageOutput)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.ERROR.Printf("Failed to resolve layout output %q for page %q: %s", outFormat.Name, page, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch pageOutput.outputFormat.Name {
|
switch pageOutput.outputFormat.Name {
|
||||||
|
@ -161,7 +165,11 @@ func (s *Site) renderPaginator(p *PageOutput) error {
|
||||||
pageNumber := i + 1
|
pageNumber := i + 1
|
||||||
addend := fmt.Sprintf("/%s/%d", paginatePath, pageNumber)
|
addend := fmt.Sprintf("/%s/%d", paginatePath, pageNumber)
|
||||||
targetPath, _ := p.targetPath(addend)
|
targetPath, _ := p.targetPath(addend)
|
||||||
layouts := p.layouts()
|
layouts, err := p.layouts()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.renderAndWritePage(
|
if err := s.renderAndWritePage(
|
||||||
pagerNode.Title,
|
pagerNode.Title,
|
||||||
|
@ -200,10 +208,13 @@ func (s *Site) renderRSS(p *PageOutput) error {
|
||||||
p.Data["Pages"] = p.Pages
|
p.Data["Pages"] = p.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
layouts := s.layoutHandler.For(
|
layouts, err := s.layoutHandler.For(
|
||||||
p.layoutDescriptor,
|
p.layoutDescriptor,
|
||||||
"",
|
"",
|
||||||
p.outputFormat)
|
p.outputFormat)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(bep) output deprecate/handle rssURI
|
// TODO(bep) output deprecate/handle rssURI
|
||||||
targetPath, err := p.targetPath()
|
targetPath, err := p.targetPath()
|
||||||
|
|
|
@ -83,19 +83,23 @@ indexes/indexes.NAME.SUFFIX indexes/indexes.SUFFIX
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format) []string {
|
func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format) ([]string, error) {
|
||||||
|
|
||||||
// We will get lots of requests for the same layouts, so avoid recalculations.
|
// We will get lots of requests for the same layouts, so avoid recalculations.
|
||||||
key := layoutCacheKey{d, layoutOverride, f}
|
key := layoutCacheKey{d, layoutOverride, f}
|
||||||
l.mu.RLock()
|
l.mu.RLock()
|
||||||
if cacheVal, found := l.cache[key]; found {
|
if cacheVal, found := l.cache[key]; found {
|
||||||
l.mu.RUnlock()
|
l.mu.RUnlock()
|
||||||
return cacheVal
|
return cacheVal, nil
|
||||||
}
|
}
|
||||||
l.mu.RUnlock()
|
l.mu.RUnlock()
|
||||||
|
|
||||||
var layouts []string
|
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
|
layout := d.Layout
|
||||||
|
|
||||||
if layoutOverride != "" {
|
if layoutOverride != "" {
|
||||||
|
@ -106,7 +110,7 @@ func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format)
|
||||||
|
|
||||||
if d.Kind == "page" {
|
if d.Kind == "page" {
|
||||||
if isRSS {
|
if isRSS {
|
||||||
return []string{}
|
return []string{}, nil
|
||||||
}
|
}
|
||||||
layouts = regularPageLayouts(d.Type, layout, f)
|
layouts = regularPageLayouts(d.Type, layout, f)
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,14 +152,14 @@ func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return layoutsWithThemeLayouts
|
return layoutsWithThemeLayouts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
l.cache[key] = layouts
|
l.cache[key] = layouts
|
||||||
l.mu.Unlock()
|
l.mu.Unlock()
|
||||||
|
|
||||||
return layouts
|
return layouts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveListTemplate(d LayoutDescriptor, f Format,
|
func resolveListTemplate(d LayoutDescriptor, f Format,
|
||||||
|
|
|
@ -68,8 +68,9 @@ func TestLayout(t *testing.T) {
|
||||||
t.Run(this.name, func(t *testing.T) {
|
t.Run(this.name, func(t *testing.T) {
|
||||||
l := NewLayoutHandler(this.hasTheme)
|
l := NewLayoutHandler(this.hasTheme)
|
||||||
|
|
||||||
layouts := l.For(this.d, this.layoutOverride, this.tp)
|
layouts, err := l.For(this.d, this.layoutOverride, this.tp)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
require.NotNil(t, layouts)
|
require.NotNil(t, layouts)
|
||||||
require.True(t, len(layouts) >= len(this.expect))
|
require.True(t, len(layouts) >= len(this.expect))
|
||||||
// Not checking the complete list for now ...
|
// Not checking the complete list for now ...
|
||||||
|
@ -83,6 +84,10 @@ 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) {
|
func BenchmarkLayout(b *testing.B) {
|
||||||
|
@ -90,7 +95,8 @@ func BenchmarkLayout(b *testing.B) {
|
||||||
l := NewLayoutHandler(false)
|
l := NewLayoutHandler(false)
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
layouts := l.For(descriptor, "", HTMLFormat)
|
layouts, err := l.For(descriptor, "", HTMLFormat)
|
||||||
|
require.NoError(b, err)
|
||||||
require.NotEmpty(b, layouts)
|
require.NotEmpty(b, layouts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue