Using `printf` with `resources.Get`

I’ve run into an oddity with printf and resources.Get. I’ve searched for hours trying to get an answer to the problem and, while I found a few similar cases, none fit it exactly enough to help. (I can’t put this on a repo right now, but I hope the following will be sufficient to explain. If not, please let me know.)

Let’s say:

  • For each post in content/posts/, I’ve created in assets/images/ a corresponding transparent PNG with that post’s title in white letters.
  • This is so I can overlay that PNG with images.Overlay on a generic background image, assets/images/background.jpg, for social/OG card purposes.
  • Each transparent PNG has been named the same as the original post’s base filename except for social-OG-text- at the start and .png at the end. For example: corresponding to the post file content/posts/2022/07/today-is-july-4th.md is an image file, images/assets/social-text-today-is-july-4th.png.
  • Thus, I want to code my head.html partial so that each post will get the social/OG image corresponding to the post’s filename.

But when I try this:

{{- if eq .Page.Type "posts" }}
	{{- $titleText := resources.Get (printf "images/social-OG-text-%s.png" .Page.File.BaseFileName) -}}
	{{- $finalFilter := (images.Overlay $titleText 0 0 ) -}}
	{{- $socImg = resources.Get "images/background.jpg" -}}
	{{- $socImg = $socImg | images.Filter $finalFilter -}}
{{- end -}}

… Hugo errors out (more info below) because, apparently, the printf isn’t giving Hugo what it wants to see. On the other hand, if I hard-code a PNG file name rather using the printf statement, it works.

In an attempt to debug this, I used the following:

{{ erroridf "%s" (resources.Get (printf "images/social-OG-text-%s.png" .Page.File.BaseFileName)) }}

…and got back repeated entries like this (substituting $MYUSERDIR for my local user dir path):

ERROR 2022/07/21 17:09:45 render of "page" failed: "/$MYUSERDIR/hugo_site/layouts/_default/baseof.html:3:4": execute of template failed: template: posts/single.html:3:4: executing "posts/single.html" at <partial "head.html" .>: error calling partial: "/$MYUSERDIR/hugo_site/layouts/partials/head.html:58:79": execute of template failed: template: partials/head.html:58:79: executing "partials/head.html" at <.Page.File.BaseFileName>: wrong type for value; expected string; got *resources.resourceAdapter

When I ran just warnf rather than erroridf, I got a WARN line for each of the PNGs I’m trying to get, complete with the full path inside assets as it should be; for example, using the post name from my earlier example:

WARN 2022/07/21 17:39:57 images/social-OG-text-today-is-july-4th.png

(…and 200+ more like that.)

Thus, the desired PNG pathname is getting built but, for whatever reason, resources.Get doesn’t like it. Whether done through printf or hard-coded, it’s a string, so I don’t know why that would matter.

In short: I presume I’m not doing the printf part correctly, but can’t figure out what I’m missing.

Will appreciate any help anyone can offer on this.

resources.Get function return *resources.resourceAdapter type.

The correct way to get the source path of successfull resources get is via .Name (string) field.

{{- $res := resources.Get "target_path" -}}
{{- warnf "%v (%T)" $res $res -}}
{{- warnf "%v (%T)" $res.Name $res.Name -}}

return:

WARN 2022/07/22 06:30:47 css/style.scss (*resources.resourceAdapter)
WARN 2022/07/22 06:30:47 css/style.scss (string)

Thanks, although I’m not sure it solves my problem. (These image assets are in assets/images, not in any page bundles.) I’ll look at it again tomorrow when I’m somewhat less bleary-eyed. :slight_smile:

The point is he can’t get a successful resource.Get with the path he provides via printf even though it appears to be a valid string and path. He’s not trying to get info from the resource after the Get. He can’t even get there.

1 Like

My bad, i only read that part of ERROR message that erroridf expect a string but got *resources.resourceAdapter.

ERROR 2022/07/21 17:09:45 render of “page” failed: “/$MYUSERDIR/hugo_site/layouts/_default/baseof.html:3:4”: execute of template failed: template: posts/single.html:3:4: executing “posts/single.html” at <partial “head.html” .>: error calling partial: “/$MYUSERDIR/hugo_site/layouts/partials/head.html:58:79”: execute of template failed: template: partials/head.html:58:79: executing “partials/head.html” at <.Page.File.BaseFileName>: wrong type for value; expected string; got *resources.resourceAdapter

1 Like

I agree that the error messages aren’t helping here, except that they seem to indicate that what I’m passing isn’t being seen as a string, for some reason — even though it should be.

Is the statement above correct?

1 Like

No, I misstated that one (tried to change all the references, but must have missed that one). It should say: images/assets/social-OG-text-today-is-july-4th.png. Sorry for the confusion. In any event, there is a correct file name for each reference and, for whatever reason, the name string doesn’t seem to please Hugo, so to speak.

I’m not speaking for @jmooring but maybe he means your image path… where images/assets/ it should be (typically) more like assets/images/

1 Like

@jmooring @gaetawoo oh, yes — sorry — assets/images/, definitely. :frowning: (I just mistyped that reference when trying to explain here.)

To avoid wasting any more of your time, I think it would be best if you were to provide a minimal reproducible example.

1 Like

@jmooring Understood. Will get a minimal repo together.

Now available at:

content/posts/_index.md does not have a corresponding image.

1 Like

Ah. So I then added a PNG ending in _index.png to cover that one, and it worked.

Then I added that same file to my real site and am still having the same errors as before (expected images.ImageSource; got resource.Resource) — but with warnf back in place, I now see among the many entries:

WARN 2022/07/22 12:06:40 %!s(<nil>)

…which suggests there’s another similarly missing image in there somewhere. So, while I’m still bug-chasing, I believe you’ve put me on the right track. Thanks!

Opinion: it would be less error-prone to use page resources for these OG images. Then you could use a generic name instead of having to match file names.

1 Like

True, but I keep multiple posts in the same folder (arranged in a content/posts/[YYYY]/[MM] format) so I assume I’d still have to give each overlay PNG file a different name rather than, say, a generic name of overlay.png.

…Unless I’m totally misunderstanding your meaning, that is.

Use leaf bundles.

content/
└── posts/
    └── 2022/
        └── 07/
            ├── my-first-post/
            │   ├── index.md
            │   └── og.png
            └── my-second-post/
                ├── index.md
                └── og.png
1 Like

Also falls in the category of if I were starting over, rather than 200+ posts into my current setup. :smiley: But, duly noted, sir. I am always grateful for your help and time!

Update: Finally found the problem. There were a few files that had typos in their names, along with two additional ones I’d just missed creating. Once there finally was a corresponding and correctly named file for each (as I’d originally thought was the case), it worked. That said: for anyone searching this in the future who’s getting started: the advice I received above is absolutely correct — i.e., go with a leaf-bundle-based approach if you think you might similarly pair images and posts. It’s a lot less trouble in the long run.

Well, post a successful example dangit!?