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.
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
+}
"github.com/spf13/hugo/media"
+ "github.com/spf13/hugo/helpers"
"github.com/spf13/hugo/output"
)
return c
}
-func (p *PageOutput) layouts(layouts ...string) []string {
+func (p *PageOutput) layouts(layouts ...string) ([]string, error) {
if len(layouts) == 0 && p.selfLayout != "" {
- return []string{p.selfLayout}
+ return []string{p.selfLayout}, nil
}
layoutOverride := ""
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...)
}
pageOutput, err := newPageOutput(p, true, outFormat)
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
}
// for list pages.
func (p *Page) checkRender() bool {
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 true
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)
}
if page.selfLayout != "" {
layouts = []string{page.selfLayout}
} 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 {
pageNumber := i + 1
addend := fmt.Sprintf("/%s/%d", paginatePath, pageNumber)
targetPath, _ := p.targetPath(addend)
- layouts := p.layouts()
+ layouts, err := p.layouts()
+
+ if err != nil {
+ return err
+ }
if err := s.renderAndWritePage(
pagerNode.Title,
p.Data["Pages"] = p.Pages
}
- layouts := s.layoutHandler.For(
+ layouts, err := s.layoutHandler.For(
p.layoutDescriptor,
"",
p.outputFormat)
+ if err != nil {
+ return err
+ }
// TODO(bep) output deprecate/handle rssURI
targetPath, err := p.targetPath()
`
)
-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.
key := layoutCacheKey{d, layoutOverride, f}
l.mu.RLock()
if cacheVal, found := l.cache[key]; found {
l.mu.RUnlock()
- return cacheVal
+ return cacheVal, nil
}
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 != "" {
if d.Kind == "page" {
if isRSS {
- return []string{}
+ return []string{}, nil
}
layouts = regularPageLayouts(d.Type, layout, f)
} else {
}
}
- return layoutsWithThemeLayouts
+ return layoutsWithThemeLayouts, nil
}
l.mu.Lock()
l.cache[key] = layouts
l.mu.Unlock()
- return layouts
+ return layouts, nil
}
func resolveListTemplate(d LayoutDescriptor, f Format,
t.Run(this.name, func(t *testing.T) {
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.True(t, len(layouts) >= len(this.expect))
// Not checking the complete list for now ...
})
}
+ l := NewLayoutHandler(false)
+ _, err := l.For(LayoutDescriptor{Kind: "taxonomyTerm", Section: "tag"}, "override", RSSFormat)
+ require.Error(t, err)
+
}
func BenchmarkLayout(b *testing.B) {
l := NewLayoutHandler(false)
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)
}
}