FaraiBikeshedComponents

render-image.html

This render hook builds off of Hugo’s built in one which allows for robust linking to page and site resources with a few of changes:

  1. Added width and height attributes to the images (this is overridden by any dimensions specified in .Attributes). Attributes can also be defined with a JSON object in the markdown title and if it is it will have presidence over .Attributes.
  2. Added warnings when a referenced image isn’t found in the site’s assets folder.
  3. Experimental support for multiple image formats. This only works when a globally resourced image (meaning under /assets) has other images with the same directory and path. It then renders it in the picture/source elements where the source elements are in ascending order of size.

Sample Usage

Emoji courtesy of OpenMoji.

Given the picture with img src set to /images/shrug.png and the directory has webp and jxl versions of it.

The following handles images with the picture/source enabled (default) and has the current source is unviewable because you don’t have JavaScript Enabled.

![A black shrug emoji](/images/shrug.png '{"id":"withpicture"}')
A black shrug emoji

The following handles images with the picture/source enabled (default) and has the current source is unviewable because you don’t have JavaScript Enabled.

![A black shrug emoji](/images/shrug.png '{"id":"nopicture", "enablePicture":false}')
A black shrug emoji

Source Code

{{- $u := urls.Parse .Destination -}}
{{- $src := $u.String -}}
{{- $dims := dict -}}
{{- $options := dict
  "enablePicture" true
-}}
{{- $altImgs := slice -}}
{{- if not $u.IsAbs -}}
  {{- $path := strings.TrimPrefix "./" $u.Path }}
  {{- $path := strings.TrimPrefix "/assets" $u.Path }}
  {{- with or (.PageInner.Resources.Get $path) (resources.Get $path) -}}
    {{- $src = .RelPermalink -}}
    {{- with $u.RawQuery -}}
      {{- $src = printf "%s?%s" $src . -}}
    {{- end -}}
    {{- with $u.Fragment -}}
      {{- $src = printf "%s#%s" $src . -}}
    {{- end -}}
    {{- $ogDir := path.Dir .RelPermalink -}}
    {{- $ogBaseName := path.BaseName .RelPermalink -}}
    {{- $ogType := .MediaType -}}
    {{- $matchStr := print (path.Join $ogDir $ogBaseName) ".*" -}}
    {{- range (resources.Match $matchStr) -}}
      {{- if ne .MediaType $ogType -}}
        {{- $altImgs = $altImgs | append (dict "srcset" .RelPermalink "size" (os.Stat .RelPermalink).Size "type" .MediaType) -}}
      {{- end -}}
    {{ end }}
    {{- $dims = merge $dims (dict "width" (string .Width) "height" (string .Height)) -}}
  {{- else -}}
    {{- warnf "Image %s referenced in %s not found." $.Destination $.PageInner.File.Filename -}}
  {{- end -}}
{{- end -}}
{{- $attributes := merge (dict "alt" .Text "src" $src) $dims .Attributes -}}
{{- with .Title -}}
    {{- if hasPrefix . `{` -}}
        {{- $attrObj := transform.Unmarshal . -}}
        {{- range $k, $v := $attrObj -}}
          {{- if isset $options $k -}}
            {{- $options = merge $options (dict $k $v) -}}
          {{- else -}}
            {{- $attributes = merge $attributes (dict $k $v) -}}
          {{- end -}}
        {{- end -}}
    {{- else -}}
        {{- $attributes = merge $attributes (dict "title" . ) -}}
    {{- end -}}
{{- end -}}
{{- $enablePicture := and $options.enablePicture (ne (len $altImgs) 0) -}}
{{- cond $enablePicture "<picture>" "" | safeHTML -}}
{{ if $enablePicture -}}
  {{ range (sort $altImgs "size" "asc") -}}
    <source srcset="{{ .srcset }}" type="{{ .type }}">
  {{- end }}
{{- end }}
<img
  {{- range $k, $v := $attributes -}}
    {{- if $v -}}
      {{- printf " %s=%q" $k $v | safeHTMLAttr -}}
    {{- end -}}
  {{- end -}}>
{{- cond $enablePicture "</picture>" "" | safeHTML -}}

TODO

  • Add support for multiple image formats via the <picture>/<source> elements.