diff --git a/layouts/_markup/render-image.html b/layouts/_markup/render-image.html
index 981b18e..eb9a418 100644
--- a/layouts/_markup/render-image.html
+++ b/layouts/_markup/render-image.html
@@ -6,21 +6,77 @@
-- figure, with its title as caption (Markdown allowed):
--
-- 
+ --
+ -- Raster images (JPEG, PNG, WebP) are converted to WebP in several widths
+ -- (srcset), so that the browser downloads the most appropriate one.
+ -- GIF (possibly animated) and SVG images are served as-is.
+ --
+ -- All images get their dimensions (to avoid layout shifts) and are lazy
+ -- loaded, except the first one of the page.
*/ -}}
{{- $u := urls.Parse .Destination -}}
-{{- $src := .Destination -}}
+{{- $attrs := dict "src" .Destination "alt" .PlainText -}}
+{{- $image := false -}}
{{- if not $u.IsAbs -}}
{{- with or (.Page.Resources.Get $u.Path) (resources.Get (strings.TrimPrefix "/" $u.Path)) -}}
- {{- $src = .RelPermalink -}}
+ {{- $image = . -}}
{{- else -}}
{{- if not (strings.HasPrefix $u.Path "/") -}}
{{- errorf "%s: image %q not found" .Page.String .Destination -}}
{{- end -}}
{{- end -}}
{{- end -}}
+
+{{- with $image -}}
+ {{- /* Note: .RelPermalink publishes the original image, only done when it is served as-is */ -}}
+ {{- if in (slice "jpeg" "png" "webp") .MediaType.SubType -}}
+ {{- /* WebP variants, no wider than the original image */ -}}
+ {{- $hint := cond (eq .MediaType.SubType "png") "drawing" "photo" -}}
+ {{- $variants := slice -}}
+ {{- range $width := slice 480 800 1200 1600 -}}
+ {{- if lt $width $image.Width -}}
+ {{- $variants = $variants | append ($image.Resize (printf "%dx webp q80 %s" $width $hint)) -}}
+ {{- end -}}
+ {{- end -}}
+ {{- if lt (len $variants) 4 -}}
+ {{- /* The original width, when smaller than the largest variant */ -}}
+ {{- $variants = $variants | append ($image.Process (printf "webp q80 %s" $hint)) -}}
+ {{- end -}}
+ {{- $srcset := slice -}}
+ {{- range $variants -}}
+ {{- $srcset = $srcset | append (printf "%s %dw" .RelPermalink .Width) -}}
+ {{- end -}}
+ {{- $largest := index $variants (sub (len $variants) 1) -}}
+ {{- $attrs = merge $attrs (dict
+ "src" $largest.RelPermalink
+ "srcset" (delimit $srcset ", ")
+ "sizes" "(max-width: 1140px) 100vw, (max-width: 1280px) 75vw, (max-width: 1440px) 55vw, 50vw"
+ "width" $largest.Width
+ "height" $largest.Height
+ ) -}}
+ {{- else if eq .MediaType.SubType "gif" -}}
+ {{- $attrs = merge $attrs (dict "src" .RelPermalink "width" .Width "height" .Height) -}}
+ {{- else -}}
+ {{- $attrs = merge $attrs (dict "src" .RelPermalink) -}}
+ {{- end -}}
+{{- end -}}
+
+{{- /* The first image of the page is often the largest visible element */ -}}
+{{- if eq .Ordinal 0 -}}
+ {{- $attrs = merge $attrs (dict "fetchpriority" "high") -}}
+{{- else -}}
+ {{- $attrs = merge $attrs (dict "loading" "lazy" "decoding" "async") -}}
+{{- end -}}
+
+{{- $img := "" -}}
+{{- range $k, $v := $attrs -}}
+ {{- $img = printf `%s %s="%s"` $img $k (string $v | htmlEscape) -}}
+{{- end -}}
+{{- $img = printf "
" $img | safeHTML -}}
+
{{- if .IsBlock -}}
-
+ {{ $img }}
{{- with .Title }}
{{- . | markdownify -}}
@@ -28,5 +84,5 @@
{{- end }}
{{- else -}}
-
+{{ $img }}
{{- end -}}
diff --git a/layouts/_partials/social-image.html b/layouts/_partials/social-image.html
index 945bb1f..31af322 100644
--- a/layouts/_partials/social-image.html
+++ b/layouts/_partials/social-image.html
@@ -43,11 +43,16 @@
{{- /* 3. The first image displayed in the page content */ -}}
{{- if and (not $source) $images -}}
+ {{- /*
+ -- The images are compared by name (without extension) since the image
+ -- render hook serves processed variants (name_hu_.webp). Do not use
+ -- .RelPermalink here: it would publish all the images of the page.
+ */ -}}
{{- range findRESubmatch `
]*\ssrc="([^"]+)"` .Content -}}
- {{- $src := index . 1 -}}
+ {{- $name := index . 1 | path.Base | replaceRE `_hu_[0-9a-f]+\.\w+$` "" | replaceRE `\.\w+$` "" -}}
{{- if not $source -}}
{{- range $images -}}
- {{- if and (not $source) (or (eq .RelPermalink $src) (eq .Permalink $src)) -}}{{- $source = . -}}{{- end -}}
+ {{- if and (not $source) (eq (replaceRE `\.\w+$` "" (path.Base .Name)) $name) -}}{{- $source = . -}}{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}