PeterSmith.Org

Figure shortcode (again)

To have responsive images, I used a shortcode for figures. I modified it to handle SVG and rotated images. Alas, I had some other problems with it (too hard to change the size of the images generated for srcset). So I have switched to the code by Charl P. Botha. It's pretty nice.

And again, I've made it work for both SVG and rotated images.

I've not done any real testing (other than checking a few of my own pages), but is seems to be good.

figure.html

  {{/*

figure with auto-resizing and srcset v2020-05-10

Drop-in replacement for Hugo's figure shortcode as of 2020-05-02 that uses img srcset
to enable browsers to download only the resolution that they need.

The resizing and srcset magic only works for images that are part of the page
bundle. It will fall back to stock Hugo figure behaviour otherwise.

Improvements that were initially out of reach of my Hugo template programming "skills"
but have now been taken care of:
- [x] gracefully handle images that are not in page bundle, i.e. no image processing available
- [x] use a single configurable sizes array, and derive everything from there

See https://cpbotha.net/2020/05/02/drop-in-replacement-for-hugo-figure-shortcode-with-img-srcset-support/

- original srcset img shortcode from: https://laurakalbag.com/processing-responsive-images-with-hugo/
- original hugo figure shortcode from: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/shortcodes/figure.html
- no unnecessary resizes and more nudges by Stéfan van der Walt https://mentat.za.net/
- mashing together and srcset logic fixes by Charl P. Botha https://cpbotha.net/

Changes:
- 2020-05-10 fall back to stock Hugo behaviour when no page bundle found
- 2020-05-04 no unnecessary resizes, sizes in array
- 2020-05-02 initial release

*/}}
{{/* hugo will resize to all of these sizes that are smaller than your original. configure if you like! */}}
{{- $sizes := (slice "240" "480" "625" "800" "1200" "1500") -}}

{{/* get file that matches the filename as specified as src="" in shortcode */}}
{{- $src := .Page.Resources.GetMatch (printf "*%s*" (.Get "src")) -}}

<!-- Check to see if the image can be processed; i.e., is is not an SVG file -->
{{- $myTransform := "" -}}
{{- if ne $src.MediaType.SubType "svg" -}}
{{- $orientation := 0 -}}
{{- with $src.Exif -}}
    {{- $orientation = .Tags.Orientation -}}
{{- end -}}
{{- if eq $orientation  "0" -}}
    {{- $myTransform = "" -}}
{{- else if eq $orientation 1 -}}
    {{- $myTransform = "" -}}
{{- else if eq $orientation 2 -}}
    {{- $myTransform = "" -}}
{{- else if eq $orientation 3 -}}
    {{- $myTransform = " r180" -}}
{{- else if eq $orientation 4 -}}
    {{- $myTransform = "" -}}
{{- else if eq $orientation 5 -}}
    {{- $myTransform = "" -}}
{{- else if eq $orientation 6 -}}
    {{- $myTransform = " r270" -}}
{{- else if eq $orientation 7 -}}
    {{- $myTransform = "" -}}
{{- else if eq $orientation 8 -}}
    {{- $myTransform = " r90" -}}
{{- else -}}
    {{- $myTransform = "" -}}
{{- end -}}
{{- end -}}

<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
    {{- if .Get "link" -}}
        <a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{- end -}}>
    {{- end }}
    <img
      {{ if $src -}}
         {{- if ne $src.MediaType.SubType "svg" -}}
            sizes="(min-width: 35em) 1200px, 100vw"
            {{/* only srcset images smaller than or equal to the src (original) image size, as Hugo will upscale small images */}}
            srcset='
            {{ range $sizes }}
                   {{ if ge $src.Width . }}{{ ($src.Resize (printf "%sx webp %s" . $myTransform)).Permalink }} {{ (printf "%sw" .) }},{{ end }}
            {{ end }}'

            {{/* when no support for srcset (old browsers, RSS), we load small (800px) */}}
            {{/* if image smaller than 800, then load the image itself */}}
            {{- if ge $src.Width "800" -}}src="{{ ($src.Resize "800x webp" ).Permalink }}"
            {{- else }}src="{{ $src.Permalink }}"{{- end -}}
        {{- else -}}
            src="{{ $src }}"
        {{- end -}}
    {{- else -}}
        {{/* fall back to stock hugo behaviour when image is not available in bundle */}}
        src="{{ .Get "src" }}"
    {{- end -}}

    {{- if or (.Get "alt") (.Get "caption") }}
        alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify| plainify }}{{ end }}"
    {{- end -}}
    {{- with .Get "width" }} width="{{ . }}"{{ end -}}
    {{- with .Get "height" }} height="{{ . }}"{{ end -}}
    /> <!-- Closing img tag -->
    {{- if .Get "link" }}</a>{{ end -}}
    {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
        <figcaption>
            {{ with (.Get "title") -}}
                <h4>{{ . }}</h4>
            {{- end -}}
            {{- if or (.Get "caption") (.Get "attr") -}}<p>
                {{- .Get "caption" | markdownify -}}
                {{- with .Get "attrlink" }}
                    <a href="{{ . }}">
                {{- end -}}
                {{- .Get "attr" | markdownify -}}
                {{- if .Get "attrlink" }}</a>{{ end }}</p>
            {{- end }}
        </figcaption>
    {{- end }}
</figure>
Updated on 22 January 2023

I've reworked the partial (again). Now I draw on my img partial that does all the heavy lifting for the srcset.

My new figure.html looks like this


  {{- $src := .Page.Resources.GetMatch (printf "*%s*" (.Get "src")) -}}

<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
    {{- if .Get "link" -}}
    <a href="{{ .Get "link" }}"
       {{ with .Get "target" }} target="{{ . }}"{{ end }}
       {{ with .Get "rel" }} rel="{{ . }}"{{- end -}}> <!-- End of a tag -->
   {{- end -}}
   {{- $alt := "" -}}
   {{- if .Get "alt" -}}
       {{- $alt = .Get "alt" -}}
   {{- else if .Get "caption" -}}
       {{- $alt = .Get "caption" -}}
   {{- else -}}
     {{- $alt = $src.Title -}}
   {{- end -}}
   {{- partial "img" (dict "img" $src "alt" $alt "photosize" 625) -}}

   {{- if .Get "link" }}</a>{{ end -}}
   {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
      <figcaption>
	{{ with (.Get "title") -}}<h4>{{ . }}</h4>{{- end -}}
	{{- if or (.Get "caption") (.Get "attr") -}}<p>
	    {{- .Get "caption" | markdownify -}}
	    {{- with .Get "attrlink" }}<a href="{{ . }}">{{- end -}}
	    {{- .Get "attr" | markdownify -}}
            {{- if .Get "attrlink" }}</a>{{ end }}</p>
	{{- end }}
      </figcaption>
   {{- end }}
</figure>

This is cleaner and shorter. It also means I only have one place (img) where I need to tinker with my responsive graphics (kind off).

Updated on 23 January 2023

Converted the update on the page to be the new (extensible) format.


Webmentions
If you webmention this page, please let me know the URL of your page.

BTW: Your webmention won't show up until I next "build" my site.

Word count: 900 (about 4 minutes)

Published:

Updated: 22 Jan '23 19:27

Author: Peter Smith

Permalink: https://petersmith.org/blog/2023/01/19/figure-shortcode-again-/

Section: blog

Kind: page

Bundle type: leaf

Source: blog/2023/01/19/figure-shortcode-again-/index.org