Una propuesta que hice de un shortcode para Hugo usando el tema Blowfish para leer información Open Graph desde una URL.
Sigue los estándares del protocolo Open Graph de Facebook Platform - Wikipedia.
Este código crea una tarjeta como la siguiente:

En caso de fallback (por ejemplo, error 403/404), mostrará un pequeño banner.
El código que debes añadir en tu entorno en layouts/shortcodes/og-card.html:
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 }}Además, añade las traducciones en la carpeta i18n: i18n/en.yaml y i18n/es.yaml.
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)."i18n/es.yaml
global:
language: "ES"
external_reference_text:
add_link: "Más información en el [link](%s) 👇"
alternative: "Más en la siguiente [referencia externa](%s)."Para usar este shortcode, escribe lo siguiente en tu post en markdown:
(observa que debes eliminar los * en el siguiente ejemplo)
content/example.md
{{*< og-card url="http://www.sqlalchemy.org" add_link=true >*}}El shortcode tiene los siguientes parámetros:
- url: La URL de la página a enlazar.
- add_link: Añade el texto de referencia definido en la variable i18n
add_link. - add_margin_bottom: Deja un espacio o margen al pie de la tarjeta Open Graph.
- add_image: Añade la imagen Open Graph.
- only_text: Muestra únicamente el texto
alternativede i18n. Sin imagen ni información adicional.
Esta idea fue publicada en los siguientes foros 👇

