Hugo

Access page resources from list templates

I got content and a theme. With my site, every page (normal and list pages) should have a image:

/content/images/A.jpg

/content/_index.md

---
title: "Hello"
date: 2019-11-03T00:00:00+00:00
image: images/A.jpg
resources:
- src: images/A.jpg
  title: "A picture"
---
# Hello

/themes/mytheme/layouts/index.html

{{ define "head" }}
	{{ if .Params.image -}}
	{{ $img := resources.Get (.Params.image) }}
	<style>
header.banner {
	background-image: url('{{ $img.RelPermalink }}');
	background-position: 50% {{.Params.image_pos_vert | default "50%"}};
}
	</style>
	{{- end -}}
{{ end }}

When I build, I get this error:

ERROR [...] Failed to render pages:
render of "home" failed:
"[...]themes/mytheme/layouts/index.html:6:31":
execute of template failed: template:
index.html:6:31:
executing "head" at <$img.RelPermalink>:
nil pointer evaluating resource.Resource.RelPermalink

Instead of resources.Get (.Params.image) I can write

.Page.Resources.Get (.Params.image)
$.Page.Resources.Get (.Params.image)
.Resources.Get (.Params.image)
$.Resources.Get (.Params.image)

$img stays pointing to nil. Getting .Params.image works as expected.

This pattern works for Pages and fails for ListPages and the HomePage.

After reading the docs, I would expect it to work for list pages, also: “This new model allows you to include list-specific front matter via .Params and also means that list templates have access to all page variables.”

Am I doing something wrong?

Hi,

Resources for list pages need to be in the same level as the _index.md: See table here https://gohugo.io/content-management/page-bundles/

Hi pointyfar,

thank you for your explaination. This clears up some things. Yet it makes me question many more (for my own answer, see after the EDIT tag):
Why is there any constraint on where my resources reside?
Is it any different when I explicitly list my resources (like in the example below)? Or do resources need to get listed in the front matter at all times (even if I do not have metadata for them; so there are no implicit resources)?

Conceptually I do not understand why this should not work:

---
title: "Hello"
resources:
- src: ../../A.jpg
  name: A.jpg
  title: "A picture"
---
<img src="{{ .Resources.Get('A.jpg').RelPermalink }}" />

I can’t find the relevant code. All I see is a generic globbing and loading of the specified files…

EDIT:
I think I just understood: When I say

Any page bundle (leaf or branch bundle) is only allowed to use its exclusive directories. It can not use resources located at a position that can be referenced by another page bundle. All page bundle resources are independet of their surrounding bundles and can be moved to arbitrary positions without breaking their resource references.
So a branch bundle can only use resources on its exact level in the directory hierachy. A leaf bundle can use resources on its own level or in any directory below.
The only exception from that rule are headless bundles, which can be the source of resources in other page bundles via a special mechanism to dereference them.

am I right?

You don’t need to list your resources in your frontmatter. You do if you need to add metadata.

Essentially, yes.


Note that this example:

will not work because:

  1. You cannot use templating logic directly in your content/markdown. You need to encapsulate it into a shortcode: https://gohugo.io/content-management/shortcodes/

  2. Page .Resources have the following methods: (see .Resources.GetMatch) https://gohugo.io/content-management/page-resources/#methods
    NOT to be confused with Hugo Pipes: (see resources.Get) https://gohugo.io/hugo-pipes/introduction/