{{- /* Image render hook. Emits intrinsic width and height so the browser can reserve space before the image loads, which is what stops the page shifting as images arrive (Cumulative Layout Shift). Hugo reports .Width/.Height for raster images it can decode; SVGs are not decoded, so the dimensions are read from the viewBox instead. Raster images in a page bundle are also resized into a webp srcset, so a phone downloads a phone-sized file instead of the full-resolution original. Markdown attributes are preserved, so `![alt](img.png){ .img-fluid }` keeps its classes. */ -}} {{- $dest := .Destination -}} {{- $res := or (.Page.Resources.GetMatch $dest) (resources.GetMatch $dest) -}} {{- /* Widths worth generating: phone, tablet, laptop, the widest the content column ever gets, and one for high-density desktop displays. Anything larger than the original is skipped - upscaling costs bytes and adds no detail. An image smaller than every target is converted at its own width, so it still gets the format saving. */ -}} {{- $targetWidths := slice 480 768 1024 1440 2048 -}} {{- /* Only formats where resizing is safe. GIFs are excluded because Hugo flattens them to a single frame, and SVG has no pixels to resize. */ -}} {{- $resizable := slice "png" "jpeg" -}} {{- /* Rendered content outlives the page it was written on: .Summary is reused on list pages and the home page, and the same HTML goes into the RSS feed. A bundle-relative destination like `hugo-logo.svg` resolves against whatever URL is displaying it, so it 404s everywhere except the post itself. Publishing the resource's own path keeps the image reachable from any context. Destinations we cannot resolve - absolute URLs, static files - are passed through untouched. */ -}} {{- $src := $dest -}} {{- $srcset := slice -}} {{- $w := "" -}} {{- $h := "" -}} {{- with $res -}} {{- $src = .RelPermalink -}} {{- if eq .MediaType.SubType "svg" -}} {{- with (findRESubmatch `viewBox="[\d.-]+ +[\d.-]+ +([\d.]+) +([\d.]+)"` .Content 1) -}} {{- $vb := index . 0 -}} {{- $w = index $vb 1 -}} {{- $h = index $vb 2 -}} {{- end -}} {{- else -}} {{- $w = .Width -}} {{- $h = .Height -}} {{- if in $resizable .MediaType.SubType -}} {{- $original := . -}} {{- /* Built by hand rather than with `where`: that function reads its second argument as a field name, not an operator, when the collection holds plain numbers - it silently matches nothing. */ -}} {{- $widths := slice -}} {{- range $target := $targetWidths -}} {{- if lt $target $original.Width -}} {{- $widths = $widths | append $target -}} {{- end -}} {{- end -}} {{- /* The image's own width is always the top tier, so a high-density display can still have every pixel - just in webp rather than the original format. It also covers images smaller than every target, which get the format saving and nothing else. */ -}} {{- $widths = $widths | append $original.Width -}} {{- range $target := $widths -}} {{- $variant := $original.Resize (printf "%dx webp q80" $target) -}} {{- $srcset = $srcset | append (printf "%s %dw" $variant.RelPermalink $variant.Width) -}} {{- /* The widest variant becomes src, so browsers ignoring srcset still get a resized file rather than the original. */ -}} {{- $src = $variant.RelPermalink -}} {{- $w = $variant.Width -}} {{- $h = $variant.Height -}} {{- end -}} {{- end -}} {{- end -}} {{- end -}} {{- /* The first image on a page is often the largest contentful paint, so it is left eager and asked for early; later ones are lazy. */ -}} {{ .Text }}