Here is a proposal of a shortcode for Open Graph. Following Facebook Platform - Wikipedia
This code will create a card like the following:
In case of fallback, will show a short banner.
The code of layouts\shortcodes\og-card.html:
{{/* layouts/shortcodes/og-card.html */}}
{{/* Provide the URL to fetch Open Graph data from */}}
{{ $url := .Get "url" | default (.Get 0) }}
{{/* Multiple additional parameters */}}
{{ $add_link := .Get "add_link" | default (.Get 1) | default true }}
{{ $add_margin_bottom := .Get "add_margin_bottom" | default (.Get 2) | default true }}
{{ $add_image := .Get "add_image" | default (.Get 3) | default true }}
{{ $only_text := .Get "only_text" | default (.Get 4) | default false }}
{{ $ogTitle := "" }}
{{ $ogDesc := "" }}
{{ $ogImage := "" }}
{{/* Regex (más tolerantes y reutilizables) */}}
{{ $reOgImage := `(?i)<meta[^>]+(?:property|name)=["'](?:og:image|twitter:image)["'][^>]+content=["']([^"']+)["']` }}
{{ $reOgTitle := `(?i)<meta[^>]+property=["']og:title["'][^>]+content=["']([^"']+)["']` }}
{{ $reOgDesc := `(?i)<meta[^>]+property=["']og:description["'][^>]+content=["']([^"']+)["']` }}
{{ $reTitleTag := `(?i)<title>(.*?)</title>` }}
{{/* Parse del URL para host/scheme */}}
{{ $u := urls.Parse $url }}
{{ $host := "" }}
{{ with $u }}{{ $host = .Host }}{{ end }}
{{/* Configuración de la petición */}}
{{ $opts := dict "headers" (dict
"User-Agent" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
"Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
"Accept-Language" "en-US,en;q=0.5"
"Referer" "https://www.google.com/"
"Upgrade-Insecure-Requests" "1"
"Sec-Ch-Ua" "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\""
"Sec-Ch-Ua-Mobile" "?0"
"Sec-Ch-Ua-Platform" "\"Windows\""
"Sec-Fetch-Dest" "document"
"Sec-Fetch-Mode" "navigate"
"Sec-Fetch-Site" "none"
"Sec-Fetch-User" "?1"
) }}
{{/* Recurso remoto. NOTA: Para activar el fallback en caso de error (403/404), agrega ignoreErrors = ["error-remote-get"] en hugo.toml */}}
{{ $resource := resources.GetRemote $url $opts }}
{{ $add_margin_bottom_class := cond $add_margin_bottom " mb-6" "" }}
{{ if and $resource (not $only_text) }}
{{ $content := $resource.Content }}
{{/* 1 IMAGEN */}}
{{ if $add_image }}
{{ with (findRE $reOgImage $content 1) }}
{{ $ogImage = index . 0 | replaceRE $reOgImage "$1" }}
{{ end }}
{{/* Normaliza og:image relativo -> absoluto */}}
{{ if and $ogImage $u }}
{{ if hasPrefix $ogImage "//" }}
{{ $ogImage = printf "%s:%s" $u.Scheme $ogImage }}
{{ else if hasPrefix $ogImage "/" }}
{{ $ogImage = printf "%s://%s%s" $u.Scheme $u.Host $ogImage }}
{{ end }}
{{ end }}
{{ end }}
{{/* 2 TÍTULO */}}
{{ with (findRE $reOgTitle $content 1) }}
{{ $ogTitle = index . 0 | replaceRE $reOgTitle "$1" }}
{{ else }}
{{ with (findRE $reTitleTag $content 1) }}
{{ $ogTitle = index . 0 | replaceRE $reTitleTag "$1" }}
{{ end }}
{{ end }}
{{/* 3 DESCRIPCIÓN */}}
{{ with (findRE $reOgDesc $content 1) }}
{{ $ogDesc = index . 0 | replaceRE $reOgDesc "$1" }}
{{ end }}
{{ if $add_link }}
{{ $content := printf (i18n "external_reference_text.add_link") $url }}
<p>{{- $content | markdownify -}}</p>
{{ end }}
<div class="my-6 w-full max-w-prose mx-auto{{ $add_margin_bottom_class }}">
<a href="{{ $url }}" target="_blank" rel="noopener noreferrer" class="not-prose block group relative overflow-hidden rounded-2xl bg-neutral-100 dark:bg-neutral-800 hover:shadow-xl transition-all duration-300 border border-neutral-200 dark:border-neutral-700/50">
{{ if $ogImage }}
<div class="aspect-video w-full overflow-hidden relative bg-neutral-200 dark:bg-neutral-700">
<img src="{{ $ogImage | safeURL }}" alt="{{ ($ogTitle | default "Preview") | htmlUnescape }}" class="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105" loading="lazy" />
</div>
{{ end }}
<div class="p-5">
<h3 class="text-lg font-bold text-neutral-900 dark:text-neutral-100 group-hover:text-primary-600 dark:group-hover:text-primary-400 leading-tight mb-2">
{{ $ogTitle | default $url | htmlUnescape }}
</h3>
{{ if $ogDesc }}
<p class="text-sm text-neutral-600 dark:text-neutral-400 line-clamp-2 mb-3">
{{ $ogDesc | htmlUnescape | truncate 140 }}
</p>
{{ end }}
<div class="flex items-center gap-2 mt-2 pt-2 border-t border-neutral-200 dark:border-neutral-700/50">
<img src="https://www.google.com/s2/favicons?domain={{ $host | default $url }}&sz=32" alt="" class="w-4 h-4 opacity-70" />
<div class="text-xs font-mono text-neutral-500">
{{ $host | default ($url | replaceRE `^https?://(www\.)?([^/]+).*` "$2") }} ↗
</div>
</div>
</div>
</a>
</div>
{{ else }}
<div class="my-6{{ $add_margin_bottom_class }}">
{{ partial "components/alert.html" (dict
"icon" "link"
"content" (printf (i18n "external_reference_text.alternative") $url)
) }}
</div>
{{ end }}
What is needed at i18n: i18n\en.yaml ![]()
global:
language: "EN"
external_reference_text:
add_link: "More information at the [link](%s) 👇"
alternative: "More in the following [external reference](%s)."
To use the shortcode:
{{< og-card url="http://www.sqlalchemy.org" add_link=true >}}
Please, open to suggestions about this idea.
Theme classes is based on https://blowfish.page/
