{{ $iso8601 := "2006-01-02T15:04:05-07:00" -}} {{- $isArticle := partial "head/is-article.html" . -}} {{- /* `profile` is Open Graph's own type for a page about a person, so an author page says so rather than falling back to `website`. The profile:first_name / profile:last_name tags are deliberately not emitted: splitting a personal name into given and family parts is wrong often enough across locales that the type alone is the safer claim. */ -}} {{- $isAuthorPage := partial "head/is-author-page.html" . -}} {{- /* Only raster formats every OG consumer supports; SVG is rejected by all of them. WebP is not dropped but converted: several consumers - LinkedIn among them - do not render it, and skipping it silently costs the page its own image. */ -}} {{- /* 1200px is the width LinkedIn needs to render a large link preview card; below it the image is demoted to a small thumbnail beside the text. Facebook and X accept the same width, so one number serves all three. */ -}} {{- $ogWidth := 1200 -}} {{- $ogFormats := slice "png" "jpeg" -}} {{- $ogImages := slice -}} {{- range $.Params.images -}} {{- with $.Resources.GetMatch . -}} {{- /* $ogWidth is a cap, not a target: never upscale a source narrower than it. .Width is read inside each branch because it exists only on raster resources, and an unsupported format such as SVG must fall through untouched. */ -}} {{- $img := "" -}} {{- if in $ogFormats .MediaType.SubType -}} {{- $w := cond (gt .Width $ogWidth) $ogWidth .Width -}} {{- $img = .Resize (printf "%dx" $w) -}} {{- else if eq .MediaType.SubType "webp" -}} {{- $w := cond (gt .Width $ogWidth) $ogWidth .Width -}} {{- $img = .Resize (printf "%dx jpeg q85" $w) -}} {{- end -}} {{- with $img -}} {{- /* .Params survives image processing while .Title does not, so alt text attached to the page resource in front matter reaches Open Graph from here. */ -}} {{- $ogImages = $ogImages | append (dict "src" .Permalink "w" .Width "h" .Height "alt" .Params.alt) -}} {{- end -}} {{- end -}} {{- end -}} {{- /* Site-level images are a fallback, not an addition. Without the emptiness check both ranges append, so any page carrying its own image emitted that image *and* the site logo. Consumers differ on which of several og:image tags they use - some take the first, some the last - so the page was effectively sharing a random one of the two. */ -}} {{- if not $ogImages -}} {{- range $.Site.Params.images -}} {{- with resources.GetMatch . -}} {{- $img := "" -}} {{- if in $ogFormats .MediaType.SubType -}} {{- $w := cond (gt .Width $ogWidth) $ogWidth .Width -}} {{- $img = .Resize (printf "%dx" $w) -}} {{- else if eq .MediaType.SubType "webp" -}} {{- $w := cond (gt .Width $ogWidth) $ogWidth .Width -}} {{- $img = .Resize (printf "%dx jpeg q85" $w) -}} {{- end -}} {{- with $img -}} {{- /* No alt: a site-wide fallback image describes the brand, not this page. */ -}} {{- $ogImages = $ogImages | append (dict "src" .Permalink "w" .Width "h" .Height) -}} {{- end -}} {{- end -}} {{- end -}} {{- end }} {{- /* width and height let a consumer lay the card out before it has fetched the image, and are what stop LinkedIn and WhatsApp guessing wrong on a slow first scrape. alt is emitted only when the page actually supplied one: an empty alt says nothing and is worse than its absence. */ -}} {{ range first 6 $ogImages }} {{- with .alt }} {{- end }} {{- end }} {{- if $isArticle }} {{- /* Only when there is a section to name: a page outside one would emit an empty article:section, which says nothing. */}} {{ with .Section }} {{ end }} {{ with .PublishDate }} {{ end }} {{ with .Lastmod }} {{ end }} {{- end -}} {{- with .Params.audio }} {{ end }} {{- /* Falls back to the page's own language. Open Graph wants the underscore form (pt_PT), while Hugo reports the locale with a hyphen. */ -}} {{- with .Params.locale | default (replace (.Language.Locale | default .Site.Language.Lang) "-" "_") }} {{ end }} {{- with .Site.Title }} {{ end }} {{- with .Params.videos }} {{- range . }} {{ end }} {{ end }} {{- /* If it is part of a series, link to related articles */}} {{- $permalink := .Permalink }} {{- range .GetTerms "series" }} {{- range first 6 .Pages }} {{- if ne .Permalink $permalink }} {{- end }} {{- end }} {{- end }}