After the last post, I thought I was finished with my Hugo/Lightbox image gallery, but there was one more thing I didn’t like: the filenames generated by Hugo’s image processing.
As a reminder, my current image gallery shortcode (including image captions from EXIF data and overlaying images with a logo) looks like this:
{{ $logo := resources.Get "img/overlay-logo.png" }}
{{ $image := (.Page.Resources.ByType "image") }}
{{ with $image }}
{{ range . }}
{{ $resized := .Fill "150x115 q20" }}
{{ $x := sub .Width (add $logo.Width 10) }}
{{ $y := sub .Height (add $logo.Height 10) }}
{{ $withlogo := .Filter (images.Overlay $logo $x $y)}}
<a href="{{ $withlogo.Permalink }}" data-lightbox="x" data-title="{{ with .Exif }}{{ .Tags.ImageDescription }}{{ end }}"><img src="{{ $resized.Permalink }}" /></a>
{{ end }}
{{ end }}
Both the thumbnail ($resized
) and the main image ($withlogo
) are created with Hugo’s image processing features, which means that their final filenames are assigned at build time by Hugo, and they are ugly.
For example one of the images from my demo project: the original filename is notebook.jpg
, but the the shortcode shown above produces this HTML:
<a href="http://localhost:1313/galleries/gallery1/img/notebook_hu3d03a01dcc18bc5be0e67db3d8d209a6_1586565_filter_6003090614434618376.jpg" data-lightbox="x" data-title="">
<img src="http://localhost:1313/galleries/gallery1/img/notebook_hu3d03a01dcc18bc5be0e67db3d8d209a6_1586565_150x115_fill_q20_box_smart1.jpg" />
</a>
1. The easy part: renaming the main image
Starting with version 0.100.0, Hugo supports renaming files after processing them, via resources.Copy
.
Unfortunately, there aren’t many examples out there yet. The only one in the docs (resources.Copy "images/mynewname.jpg"
) doesn’t help me, because it uses a fixed filename, and I need dynamic filenames because I’m dealing with lists of images.
But this one case is easy: I want to give the processed image its original filename back, the one that it had before processing.
As I’m looping all images anyway and processing each one in the loop, the original filename with its complete path, which resources.Copy
needs, is still accessible via .RelPermalink
.
(.
is the current image)
So it’s just a matter of changing this line:
{{ $withlogo := .Filter (images.Overlay $logo $x $y)}}
…to this:
{{ $withlogo := .Filter (images.Overlay $logo $x $y) | resources.Copy .RelPermalink }}
As always, here’s the commit with the changes in the demo project.
The resulting HTML now looks like this:
<a href="http://localhost:1313/galleries/gallery1/img/notebook.jpg" data-lightbox="x" data-title="">
<img src="http://localhost:1313/galleries/gallery1/img/notebook_hu3d03a01dcc18bc5be0e67db3d8d209a6_1586565_150x115_fill_q20_box_smart1.jpg" />
</a>
Already better than before, but the thumbnail still has an ugly filename.
2. The not-so-easy part: renaming the thumbnail
In past image galleries, I had used a suffix like _t
for the thumbnails’ filenames, e.g. notebook.jpg
would have a thumbnail named notebook_t.jpg
.
This means that I would have to build the new file path from scratch:
path + original filename + "_t" + original file extension
So how do you do this in Hugo’s templating language?
-
You build strings via
printf
.Example:
{{ printf "%s%s" "foo" "bar" }}
⇒foobar
-
There are multiple
path.xyz
methods which expect the complete path to a file and return parts of it (what I need: directory, filename, extension).Example:
{{ path.BaseName .RelPermalink }}
⇒ fornotebook.jpg
as the current image in a loop, like in the example above, this returnsnotebook
Syntax: Similar to a lot of other programming languages, nested function calls in Hugo’s template language must be in parentheses.
I.e. if I want to use the printf
example from above, but instead of "foo"
I want to pass the path.BaseName
example (also from above), the correct syntax is:
{{ printf "%s%s" (path.BaseName .RelPermalink) "bar" }}
So this is the line of the shortcode that creates the thumbnails, which must be replaced:
{{ $resized := .Fill "150x115 q20" }}
And the new version which creates path + original filename + "_t" + original file extension
filenames as intended:
{{ $thumbname := printf "%s/%s%s%s" (path.Dir .RelPermalink) (path.BaseName .RelPermalink) "_t" (path.Ext .RelPermalink) }}
{{ $resized := .Fill "150x115 q20" | resources.Copy $thumbname }}
The commit with this change is here.
3. Conclusion
Here is the final shortcode one last time - with EXIF image captions, logo overlays and pretty filenames:
{{ $logo := resources.Get "img/overlay-logo.png" }}
{{ $image := (.Page.Resources.ByType "image") }}
{{ with $image }}
{{ range . }}
{{ $thumbname := printf "%s/%s%s%s" (path.Dir .RelPermalink) (path.BaseName .RelPermalink) "_t" (path.Ext .RelPermalink) }}
{{ $resized := .Fill "150x115 q20" | resources.Copy $thumbname }}
{{ $x := sub .Width (add $logo.Width 10) }}
{{ $y := sub .Height (add $logo.Height 10) }}
{{ $withlogo := .Filter (images.Overlay $logo $x $y) | resources.Copy .RelPermalink }}
<a href="{{ $withlogo.Permalink }}" data-lightbox="x" data-title="{{ with .Exif }}{{ .Tags.ImageDescription }}{{ end }}"><img src="{{ $resized.Permalink }}" /></a>
{{ end }}
{{ end }}
For the same demo image as above (notebook.jpg
), the HTML produced by this shortcode looks like this:
<a href="http://localhost:1313/galleries/gallery1/img/notebook.jpg" data-lightbox="x" data-title="">
<img src="http://localhost:1313/galleries/gallery1/img/notebook_t.jpg" />
</a>
Top comments (0)