Unbundle a Page Bundle

After changes in Hugo 0.123 moving forward I finally decided to embrace a page bundles to help me better manage resources that belong to selected pages. When started reading about Page Bundles vs Leaf Bundle and try on my own I faced some confusion that would like to get help to understand please.

Let me start with introduction:

content/
├── about.md
├── images/
│   ├── 2024/
│   │   ├── 01/
│   │   │   ├── this-image-1.jpg
│   │   │   ├── other-image.jpg
│   │   │   ├── fancy-picture.jpg

Part of front matter

---
title: 'About Us'
url: '/about/'
featuredImage: "/images/2024/01/this-image-1.jpg"
---

Text

![the other image](/images/2024/01/other-image.jpg)

Some more text

![the fancy picture of something](/images/2024/01/fancy-picture.jpg)

To make easier to manage resources I moved this into page bundle

content/
|── about/
|     |── index.md
|     |── this-image-1.jpg
|     |── other-image.jpg
|     |── fancy-picture.jpg

So the markdown become much simpler

---
title: 'About Us'
url: '/about/'
featuredImage: "this-image-1.jpg"
---

Text

![the other image](other-image.jpg)

Some more text

![the fancy picture of something](fancy-picture.jpg)

ps. I understand that I may not need url in such instance, but want to keep it for simplicifaction.

The render-image.html got this part in:

{{ $image := "" }}
{{ if .Page.BundleType }}
{{ $image = .Page.Resources.GetMatch .Destination }}
{{ else }}
{{ $image = resources.Get .Destination }}
{{ end }}

Which working nicely if page is not a page bundle, to catch resources from a path like /images/2024/01... and when page is a page bundle to catch resources directly.

Now, I would like to add section to about, but keeping the main page as well.

So, there will be /about/ but later I want to add /about/associations/

As I understand, I cannot put page bundle inside page bundle, as this is not working.

I cannot change /about/index.md to /about/_index.md as in that case page /about/ is not rendering even that when there is /about/associations/index.md and is rendering under /about/associations/. Thats because _index.md is used for something else.

Whats the approach to unbundle /about/ part allowing to have sub folders as a page bundles, but without braking images and need to change from just (other-image.jpg) back to (/about/other-image.jpg). Assume that /about/index.md will need to be /about/about.md to work.

Is there any ay to approach this correctly?

Maybe its just render-image.html that need to be adjusted?

I am thinking that incorporating, in a middle resources.GetMatch (or resources.Match?) for non-BundleType will allow mixed non-bundle (if link is relative or absolute) and bundle approach without need to rewrite path to files?

Please help me understand this :slight_smile:

If you want a page to have descendants, it must be a section.

Though so,
think to get this approach sorted, I need to rephrase what I am looking to do.

The render-image code

{{ $image := "" }}
{{ if .Page.BundleType }}
{{ $image = .Page.Resources.GetMatch .Destination }}
{{ else }}
{{ $image = resources.Get .Destination }}
{{ end }}

consider 2 approaches

  1. if is page bundle, its looking for reference pictures in folder where index.md file is placed
  2. if page is not bundle, its looking to get file from PATH (that need to include path to folder).

Is there a way to incporporate, in a middle of that if page is NOT bundle to hava a logic.

  1. if image is like “image.jpg” (PATTERN) to look in same PATH as page (specified URL)
  2. else use PATH approach {{ $image = resources.Get .Destination }}

Have a look at how the embedded image render hook handles this. This and the embedded link render hook are enabled by default for multilingual single-host sites.

1 Like

Thank you. Will have a look.

looking there {{ $u.IsAbs }} approach is something that I can incorporate :slight_smile:
Will work with that.

Keep in mind that .IsAbs only returns true when the scheme is non-empty.

function reference: https://gohugo.io/functions/urls/parse/

1 Like

Ok, I have re-looked on what I want to achieve and I think I cannot do that, please correct me if I am wrong.

Looking at embedded image render hook.

If Page is a Page Bundle the images require PATTERN

![image](image-in-same-folder-as-index-md.jpg)

this will use .Page.Resources.Get $u.Path

If Page is not Page Bundle than I need to use PATH on images like

![image](/images/somewhare/in/assets/dir/image.jpg)

to be able to use resources.Get $u.Path


In that case, I cannot use this approach

![image](image-in-same-folder-as-index-md.jpg)

with sections - pages that are not Page Bundles.

as the $u.Path will return just image-in-same-folder-as-index-md.jpg and not a path to the file where is located in tree structure hence cannot be taken by resources.Get and processed further as an asset.

Correct me if I am wrong in my assumption.

  1. On Page Bundles I can specify image filename (PATTERN) to render
  2. On non-Page Bundles I always need to specify PATH to file

and there is no part-solution?

I’ve read your post a few times and I don’t understand what you want.

  • .Page.Resources.Get takes a path relative to a leaf (index.md) or branch (_index.md) bundle
  • resources.Get takes a path relative to the assets directory

If you also want to check for images in the current section, add a third check:

{{ d:= .Destination }}
{{ $r := or
  (.Page.Resources.Get $d) 
  (.Page.CurrentSection.Resources.Get $d)   
  (or resources.Get $d)
}}

The embedded image render hook falls back to the provided path (passes it through) if a resource is not found.

1 Like

I am sorry, I think I make it overcomplicated at start.

I am looking to create simple render-image.html like

{{ $image := "" }}

{{ $image := $image.Resize "480x webp" }}
<img src="{{ $image.RelPermalink }}" />

For Page Bundle bundle (index.md), with markdown image ![image](test-image.jpg) it will be

{{ $image := "" }}
{{ $image := .Page.Resources.GetMatch .Destination }}
{{ $image := $image.Resize "480x webp" }}
<img src="{{ $image.RelPermalink }}" />

For Non-Page bundle about.md the markdown need to specify precise PATH to file ![image](/images/test-image.jpg) and the code will be:

{{ $image := "" }}
{{ $image = resources.Get .Destination }}
{{ $image := $image.Resize "480x webp" }}
<img src="{{ $image.RelPermalink }}" />

What I want to do, to get a code that will accept markdown format for image ![image](test-image.jpg) and will get the resource from same folder where about.md file is, so I don’t need to specify precise PATH to file, as the file will be in same folder as markdown file.

I tried this

{{ $image := "" }}
{{ $image = .Page.CurrentSection.Resources.Get .Destination }}
{{ $image := $image.Resize "480x webp" }}
<img src="{{ $image.RelPermalink }}" />

For Non-Page bundle file with, but still facing nil pointer evaluating resource.Resource.Resize because it probably required Page Bundle for that.

Hope that help.

If is not possible, thats fine, I will need to work with some markdown (non-page-bundles) files with PATH and others (page-bundles) with PATTERN for image.

Thank you for your time.

And once I posted the above I follow the (other) error from this post on forum to find my answer.

The answer is:

{{ $image := "" }}
{{ $path := path.Join .Page.File.Dir .Destination }}
{{ $image = resources.Get $path }}
{{ $image := $image.Resize "480x webp" }}
<img src="{{ $image.RelPermalink }}" />

Sometimes you need to say it loud (write) to find your answer.

Now I will just need to conditionally combine all 3 together into one :slight_smile:

I think you are overwriting your image in the last line. And odds it really necessary to initialize out to an empty string at the start?

In this example, yes, just to simplify things.

On the last answer, when I do not add {{ $image := "" }} it will throw an error:

execute of template failed: template: _default/_markup/render-image.html:3:26: executing "_default/_markup/render-image.html" at <$path>: undefined variable: $image

I will come back with my final code.

Ok, I come with such a 4-way solution.

{{ $image := "" }}
{{ if .Page.BundleType }}
    {{if hasPrefix .Destination "/" }}
        {{ $image = resources.Get .Destination }}
    {{ else }}
        {{ $image = .Page.Resources.GetMatch .Destination }}
    {{ end }}
{{ else }}
    {{if hasPrefix .Destination "/" }}
        {{ $image = resources.Get .Destination }}
    {{ else }}
        {{ $path := path.Join .Page.File.Dir .Destination }}
        {{ $image = resources.Get $path }}
    {{ end }}
{{ end }}

{{ $image := $image.Resize "480x webp" }}
<img src="{{ $image.RelPermalink }}" />
  1. if PAGE BUNDLE
    1.1. if link to PATH ie. ![image](/images/2024/image.jpg)
    1.2. if link to PATTERN (file in page bundle folder) ![image](image.jpg)
  2. if not page bundle
    1.1. if link to PATH ie. ![image](/images/2024/image.jpg)
    1.2. if link to PATTERN (file in same folder as markdown file) ![image](image.jpg)

Any feedback, if thats the right approach, appreciated.

You can factor out the code for path beginning with / as that seems to be the same in both cases

Right,

{{ $image := "" }}
{{ if hasPrefix .Destination "/" }}
    {{ $image = resources.Get .Destination }}
{{ else }}
    {{ if .Page.BundleType }}
        {{ $image = .Page.Resources.GetMatch .Destination }}
    {{ else }}
        {{ $path := path.Join .Page.File.Dir .Destination }}
        {{ $image = resources.Get $path }}
    {{ end }}
{{ end }}

{{ $image := $image.Resize "480x webp" }}
<img src="{{ $image.RelPermalink }}" />

I’d also add a with $image before resizing and print a warning with the path if the image resource can’t be found.

1 Like

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