How to get relative path to image in content directory?

Folder structure

content/
├─ section-1/
│  ├─ article-1-1/
│  │  ├─ _index.md
│  │  ├─ img1.png
│  ├─ article-1-2/
│  │  ├─ _index.md
│  ├─ _index.md
├─ section-2/
│  ├─ article-2-1/
│  ├─ article-2-2/
│  ├─ _index.md

article-1.1/_index.md

---
url: "article-1-1"
---

{{ figure src="img1.png" }}

article-2.2/_index.md

---
url: "article-2-2"
---

{{ figure src="/article-1-1/img1.png" }}

layouts/shortcodes/figure.html

{{ $src := .Get "src" }}

<img src="{{ with $src }}{{ if eq (substr . 0 1) "/" }} src="{{ . }}"{{ else }} src="/{{ $.Page.Params.url }}/{{ . }}"{{ end }}{{ end }}?v={{ readFile "RELATIVE/PATH/TO/IMG1" | md5  }}">

What I want to achieve

  • To improve the performance of my website I want to add the http-header Cache-Control "public, max-age=31536000, immutable" to all my static files.
  • Sometimes I will update my images without changing the file name, so I need a cache busting solution. I decided to add a query string to the file as mentioned in this topic.

Question

How can I get the relative path to an image which is in a content directory with highly nested sections and url front matter?

To keep it easier: Who knows what to add as the relative path in ?v={{ readFile "RELATIVE/PATH/TO/IMG1" | md5 }}"?

Instead of readFile use the Page Resources methods. It will be much simpler as the image assets are relative to their Page Bundle parent.

Do you mean something like ?v={{ (.Resources.GetMatch $src).Content | md5 }}?

This might work for {{ figure src="img1.png" }} in article-1.1/_index.md.

But it wouldn’t work for {{ figure src="/article-1-1/img1.png" }} in article-2.2/_index.md.

The docs say:

Page resources are only available to the page with which they are bundled.

But…

it would be possible if we could set the Page Bundle parent based on the URL given in the src: So {{ figure src="/article-1-1/img1.png" }} would translate in “get the resource img1.png relative to the Page Bundle parent with url: "article-1-1"”.

Yes, that is what I meant.

I haven’t tried that myself, curious to see if it works for you.

But how can I set the Page Bundle parent based on the URL given in the src?

Try {{ .Page.Parent.GetMatch "myimage*" }}

Also see this GitHub issue: Bundled pages should have .Parent set to its owner · Issue #4582 · gohugoio/hugo · GitHub

OR

Perhaps another method would be to use path.Dir | Hugo in conjunction with the method discussed in this forum topic: How to retrieve parent folder name in Page Bundles

If you look at my folder structure you will see that the parent of article-2-2 is section-2 while the parent of img1.png is section-1.

I am afraid that I don’t quite have the time to look into the complexity of your setup, in more detail.

Basically you want to fetch {{ figure src="/article-1-1/img1.png" }} from another Page Bundle under a different section article-2.2/_index.md.

The md5 fingerprinting function is available for Resources.

It is true that getting another Page Bundle’s assets is not straightforward. However the File templates are even more cumbersome (at list in my opinion).

What I would do to simplify my life -if I were in your shoes- would be to map the contentDir also as the assetDir.

Then within your figure shortcode I would simply do:

{{ (resources.Get $src).Content | md5 }}

The method to create a Resource from a File that resides relative to the Assets Directory is perhaps the most flexible method to give you what you ask.

In a couple of my projects I have already mapped the contentDir as the assetDir and never encountered any problem.

Also perhaps the others can offer a better way to approach this issue.

1 Like

Thank you so much for your input.

To map the contentDir also as the assetDir is a very nice hack!

Not really.

One can have multiple contentDirs and assetDirs in Hugo.

What matters is to get the job over and done with.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.