J’ai remarqué que mes articles s’affichaient sans l’image mise en avant lorsque je les partage sur Mastodon, ce qui est très agaçant. J’ai cherché pourquoi et trouvé deux solutions.
Mastodon essaie d’abord de construire une preview sur la base des meta OpenGraph, et il m’en manquait. Il faut, à minima :
- og:type
- og:title
- og:description
- og:image
- og:url
- og:locale
Sinon, Mastodon récupère les données intéressantes d’un lien via l’adresse présente dans les entêtes de la page du post :
<link rel="alternate" type="application/json+oembed" href=...>
Cette URL retourne du JSON, généré par WordPress, sous le format suivant :
{ "version": "1.0", "provider_name": "colin@colino.net", "provider_url": "https://www.colino.net/wordpress", "author_name": "Colin", "author_url": "/wordpress/archives/author/colin/", "title": "Au revoir Twitter, et merci !", "type": "rich", "width": 600, "height": 338, "html": "<blockquote class=\"wp-embedded-content\" data-secret=\"YsQM2MlHiO\"><a href=\"/wordpress/archives/2022/11/27/au-revoir-twitter-et-merci/\">Au revoir Twitter, et merci !</a></blockquote><iframe sandbox=\"allow-scripts\" security=\"restricted\" src=\"/wordpress/archives/2022/11/27/au-revoir-twitter-et-merci/embed/#?secret=YsQM2MlHiO\" width=\"600\" height=\"338\" title=\"« Au revoir Twitter, et merci ! » — colin@colino.net\" data-secret=\"YsQM2MlHiO\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\" class=\"wp-embedded-content\"></iframe><script type=\"text/javascript\">\n/*! This file is auto-generated */\n!function(c,l){\"use strict\";var e=!1,o=!1;if(l.querySelector)if(c.addEventListener)e=!0;if(c.wp=c.wp||{},c.wp.receiveEmbedMessage);else if(c.wp.receiveEmbedMessage=function(e){var t=e.data;if(!t);else if(!(t.secret||t.message||t.value));else if(/[^a-zA-Z0-9]/.test(t.secret));else{for(var r,s,a,i=l.querySelectorAll('iframe[data-secret=\"'+t.secret+'\"]'),n=l.querySelectorAll('blockquote[data-secret=\"'+t.secret+'\"]'),o=0;o<n.length;o++)n[o].style.display=\"none\";for(o=0;o<i.length;o++)if(r=i[o],e.source!==r.contentWindow);else{if(r.removeAttribute(\"style\"),\"height\"===t.message){if(1e3<(s=parseInt(t.value,10)))s=1e3;else if(~~s<200)s=200;r.height=s}if(\"link\"===t.message)if(s=l.createElement(\"a\"),a=l.createElement(\"a\"),s.href=r.getAttribute(\"src\"),a.href=t.value,a.host===s.host)if(l.activeElement===r)c.top.location.href=t.value}}},e)c.addEventListener(\"message\",c.wp.receiveEmbedMessage,!1),l.addEventListener(\"DOMContentLoaded\",t,!1),c.addEventListener(\"load\",t,!1);function t(){if(o);else{o=!0;for(var e,t,r,s=-1!==navigator.appVersion.indexOf(\"MSIE 10\"),a=!!navigator.userAgent.match(/Trident.*rv:11\\./),i=l.querySelectorAll(\"iframe.wp-embedded-content\"),n=0;n<i.length;n++){if(!(r=(t=i[n]).getAttribute(\"data-secret\")))r=Math.random().toString(36).substr(2,10),t.src+=\"#?secret=\"+r,t.setAttribute(\"data-secret\",r);if(s||a)(e=t.cloneNode(!0)).removeAttribute(\"security\"),t.parentNode.replaceChild(e,t);t.contentWindow.postMessage({message:\"ready\",secret:r},\"*\")}}}}(window,document);\n</script>\n", "thumbnail_url": "/wordpress/wp-content/uploads/image-59.png", "thumbnail_width": 600, "thumbnail_height": 305 }
Mastodon ne veut rien avoir à voir avec un OEmbed de type: rich, expliquant pourquoi dans son code source :
case @card.type when 'link' @card.image_remote_url = (url + embed[:thumbnail_url]).to_s if embed[:thumbnail_url].present? when 'photo' return false if embed[:url].blank? @card.embed_url = (url + embed[:url]).to_s @card.image_remote_url = (url + embed[:url]).to_s @card.width = embed[:width].presence || 0 @card.height = embed[:height].presence || 0 when 'video' @card.width = embed[:width].presence || 0 @card.height = embed[:height].presence || 0 @card.html = Sanitize.fragment(embed[:html], Sanitize::Config::MASTODON_OEMBED) @card.image_remote_url = (url + embed[:thumbnail_url]).to_s if embed[:thumbnail_url].present? when 'rich' # Most providers rely on <script> tags, which is a no-no return false end
Cela se comprend aisément : personne de sain d’esprit n’a envie d’injecter du javascript aléatoirement dans une autre page. Heureusement, nous pouvons corriger le générateur d’OEmbed de WordPress grâce à un filtre. Pour cela, on peut ajouter ce filtre dans le fichier functions.php de notre thème enfant, supprimer le champ html and positionner le type à link :
/* Return link instead of rich oembed data */ function filter_oembed_response_data($data) { if ($data['type'] === 'rich') { $data['type'] = 'link'; unset($data['html']); } /* while we're at it remove single quotes html entities */ $data["title"] = str_replace("’","'", $data["title"]); return $data; } add_filter('oembed_response_data', 'filter_oembed_response_data', 11, 4);
Enfin, Mastodon n’utilisera pas une image de plus de 2Mo. WordPress jusqu’à la version 6.6.2, à minima, envoie les images pleine taille en thumbnail_url, ce qui peut rapidement dépasser cette limite. Voir #62094.
Avant / après :
Je n’ai jamais eu ce problème. L’image mise en avant apparaît bien dans mes pouets.
Curieux :) peut-être qu’il me manque des tags og: pour que récupérer le oembed soit inutile ou je ne sais quoi.
Tu as tout à fait raison. Mastodon préfère les tags og: et fallback sur oembed s’il ne trouve pas tout ce qu’il veut, et il me manquait au moins :
– og:type
– og:locale
Merci !
Bah j’ai rien fait, je ne sais même pas ce qu’est un og… :-)
C’est des tags OpenGraph, c’est ton plugin Yoast SEO qui les met :)
La semaine commence bien quand on apprend quelque chose le lundi matin. :-)