Put a page's representative image behind one partial
og:image and JSON-LD's image want the same picture, chosen the same way, and computing that twice is how the two end up disagreeing. page-image.html takes a page and returns a dict of url/width/height; nothing uses it yet. The priority is the one opengraph.html already had - front matter `images`, then the generated og-card.png, then the site avatar - with one correction carried in: the og-card step now requires the page to be in the posts section rather than merely being a .IsPage. flake.nix finds what to screenshot by globbing $out for /YYYY/MM/DD/slug/ directories, so a standalone page is a .IsPage that no og-card.png is ever written for, and would otherwise advertise a 404 as its card image. It falls through to the avatar instead. width/height are 0 when unknown, which is only the front-matter case: an arbitrary reader-supplied path is not a Hugo resource this can measure.
c2b139d parent: cdc5ae7 added
blog/layouts/partials/page-image.html +47 -0 | new file mode 100644 | ||
| @@ -0,0 +1,47 @@ | ||
| 1 | +{{- /* | |
| 2 | + The image that represents a page - shared between opengraph.html (og:image/ | |
| 3 | + twitter:image) and jsonld.html (BlogPosting.image), so the same priority | |
| 4 | + logic can't drift between the two the way it would copied twice. Takes the | |
| 5 | + page being rendered, returns a dict of url/width/height (width/height 0 | |
| 6 | + when unknown, which is only the front-matter-`images` case: an arbitrary | |
| 7 | + reader-supplied path isn't a Hugo resource this can measure). | |
| 8 | + | |
| 9 | + Priority: front matter `images` (Hugo's own convention) wins, in case a | |
| 10 | + post ever wants to hand-pick its own; then the generated card every post | |
| 11 | + gets (og-card.png, a real Chromium screenshot of this same page taken by | |
| 12 | + flake.nix's buildPhase - not present under plain `hugo`/`hugo server`, | |
| 13 | + only the Nix build, so a local preview falls through to the avatar | |
| 14 | + instead); the site avatar is the last resort so a page never has no image | |
| 15 | + at all. | |
| 16 | + | |
| 17 | + The og-card step is for posts specifically, not for pages in general: | |
| 18 | + flake.nix finds what to screenshot by globbing $out for /YYYY/MM/DD/slug/ | |
| 19 | + directories, which is the posts permalink pattern from hugo.toml and | |
| 20 | + nothing else. A standalone page - /talks/ - is a .IsPage all the same, so | |
| 21 | + testing that alone had it advertise an og-card.png that no build step ever | |
| 22 | + writes. It falls through to the avatar instead, which is a real image. | |
| 23 | +*/ -}} | |
| 24 | +{{- $page := . }} | |
| 25 | +{{- $url := "" }} | |
| 26 | +{{- $width := 0 }} | |
| 27 | +{{- $height := 0 }} | |
| 28 | + | |
| 29 | +{{- with $page.Params.images }} | |
| 30 | + {{- with index . 0 }}{{ $url = . | absURL }}{{ end }} | |
| 31 | +{{- end }} | |
| 32 | +{{- if and (not $url) $page.IsPage (eq $page.Section "posts") }} | |
| 33 | + {{- $url = printf "%sog-card.png" $page.Permalink }} | |
| 34 | + {{- $width = 1200 }} | |
| 35 | + {{- $height = 630 }} | |
| 36 | +{{- end }} | |
| 37 | +{{- if not $url }} | |
| 38 | + {{- with site.Params.profile.avatar }} | |
| 39 | + {{- with resources.Get . }} | |
| 40 | + {{- $url = .Permalink }} | |
| 41 | + {{- $width = .Width }} | |
| 42 | + {{- $height = .Height }} | |
| 43 | + {{- end }} | |
| 44 | + {{- end }} | |
| 45 | +{{- end }} | |
| 46 | + | |
| 47 | +{{- return (dict "url" $url "width" $width "height" $height) }} | |
| new file mode 100644 | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | +{{- /* | ||
| 2 | + The image that represents a page - shared between opengraph.html (og:image/ | ||
| 3 | + twitter:image) and jsonld.html (BlogPosting.image), so the same priority | ||
| 4 | + logic can't drift between the two the way it would copied twice. Takes the | ||
| 5 | + page being rendered, returns a dict of url/width/height (width/height 0 | ||
| 6 | + when unknown, which is only the front-matter-`images` case: an arbitrary | ||
| 7 | + reader-supplied path isn't a Hugo resource this can measure). | ||
| 8 | + | ||
| 9 | + Priority: front matter `images` (Hugo's own convention) wins, in case a | ||
| 10 | + post ever wants to hand-pick its own; then the generated card every post | ||
| 11 | + gets (og-card.png, a real Chromium screenshot of this same page taken by | ||
| 12 | + flake.nix's buildPhase - not present under plain `hugo`/`hugo server`, | ||
| 13 | + only the Nix build, so a local preview falls through to the avatar | ||
| 14 | + instead); the site avatar is the last resort so a page never has no image | ||
| 15 | + at all. | ||
| 16 | + | ||
| 17 | + The og-card step is for posts specifically, not for pages in general: | ||
| 18 | + flake.nix finds what to screenshot by globbing $out for /YYYY/MM/DD/slug/ | ||
| 19 | + directories, which is the posts permalink pattern from hugo.toml and | ||
| 20 | + nothing else. A standalone page - /talks/ - is a .IsPage all the same, so | ||
| 21 | + testing that alone had it advertise an og-card.png that no build step ever | ||
| 22 | + writes. It falls through to the avatar instead, which is a real image. | ||
| 23 | +*/ -}} | ||
| 24 | +{{- $page := . }} | ||
| 25 | +{{- $url := "" }} | ||
| 26 | +{{- $width := 0 }} | ||
| 27 | +{{- $height := 0 }} | ||
| 28 | + | ||
| 29 | +{{- with $page.Params.images }} | ||
| 30 | + {{- with index . 0 }}{{ $url = . | absURL }}{{ end }} | ||
| 31 | +{{- end }} | ||
| 32 | +{{- if and (not $url) $page.IsPage (eq $page.Section "posts") }} | ||
| 33 | + {{- $url = printf "%sog-card.png" $page.Permalink }} | ||
| 34 | + {{- $width = 1200 }} | ||
| 35 | + {{- $height = 630 }} | ||
| 36 | +{{- end }} | ||
| 37 | +{{- if not $url }} | ||
| 38 | + {{- with site.Params.profile.avatar }} | ||
| 39 | + {{- with resources.Get . }} | ||
| 40 | + {{- $url = .Permalink }} | ||
| 41 | + {{- $width = .Width }} | ||
| 42 | + {{- $height = .Height }} | ||
| 43 | + {{- end }} | ||
| 44 | + {{- end }} | ||
| 45 | +{{- end }} | ||
| 46 | + | ||
| 47 | +{{- return (dict "url" $url "width" $width "height" $height) }} | ||