Script d'aperçu des liens sur Yakihonne
Par défaut la génération des aperçus des liens ne fonctionne pas sur Yakihonne.com. #yakihonne #nostrfr
Pour résoudre ce problème, j’ai trouvé l’astuce suivante :
- Installer l’extension Tampermonkey
- Dans les paramètres de l’extension autoriser les scripts utilisateur

- Dans Tampermonkey créer le script suivant :
// ==UserScript==
// @name Yakihonne - Aperçus URL carte compacte
// @namespace local.yakihonne.preview
// @version 2.2
// @description Affiche une carte compacte avec image complète à gauche et titre centré à droite
// @match https://yakihonne.com/*
// @grant GM_xmlhttpRequest
// @connect *
// ==/UserScript==
(function () {
'use strict';
const processed = new Set();
const style = document.createElement('style');
style.textContent = `
.yh-preview-card {
display: flex;
align-items: stretch;
width: 100%;
max-width: 100%;
height: 96px;
margin: 8px 0 10px 0;
border: 1px solid #ddd;
border-radius: 14px;
overflow: hidden;
background: #f7f3f1;
text-decoration: none;
cursor: pointer;
box-sizing: border-box;
}
.yh-preview-card:hover {
background: #f0ecea;
}
.yh-preview-image {
width: 220px;
min-width: 220px;
height: 100%;
overflow: hidden;
background: #f7f3f1;
display: flex;
align-items: center;
justify-content: center;
}
.yh-preview-image img {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
background: #f7f3f1;
}
.yh-preview-title {
flex: 1;
min-width: 0;
padding: 10px 14px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: #111;
font-size: 16px;
font-weight: 700;
line-height: 1.25;
}
.yh-preview-title span {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
@media (max-width: 700px) {
.yh-preview-image {
width: 140px;
min-width: 140px;
}
.yh-preview-title {
font-size: 14px;
padding: 8px;
}
}
`;
document.head.appendChild(style);
function escapeHtml(text) {
return String(text || '').replace(/[&<>"']/g, c => ({
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[c]));
}
function meta(doc, selector) {
return doc.querySelector(selector)?.getAttribute('content') || '';
}
function absoluteUrl(value, base) {
try {
return new URL(value, base).href;
} catch {
return '';
}
}
function fetchPreview(url) {
return new Promise(resolve => {
GM_xmlhttpRequest({
method: 'GET',
url,
timeout: 15000,
onload: res => {
try {
const doc = new DOMParser().parseFromString(
res.responseText,
'text/html'
);
const title =
meta(doc, 'meta[property="og:title"]') ||
meta(doc, 'meta[name="twitter:title"]') ||
doc.querySelector('title')?.textContent ||
url;
const image =
meta(doc, 'meta[property="og:image"]') ||
meta(doc, 'meta[name="twitter:image"]') ||
'';
resolve({
url,
title: title.trim(),
image: absoluteUrl(image, url)
});
} catch {
resolve(null);
}
},
onerror: () => resolve(null),
ontimeout: () => resolve(null)
});
});
}
function createCard(data) {
if (!data.image) return null;
const card = document.createElement('a');
card.className = 'yh-preview-card';
card.href = data.url;
card.target = '_blank';
card.rel = 'noopener noreferrer';
card.innerHTML = `
<div class="yh-preview-image">
<img src="${escapeHtml(data.image)}" loading="lazy">
</div>
<div class="yh-preview-title">
<span>${escapeHtml(data.title)}</span>
</div>
`;
card.addEventListener('click', function (e) {
e.preventDefault();
e.stopPropagation();
window.open(data.url, '_blank', 'noopener,noreferrer');
}, true);
return card;
}
async function scanLinks() {
const links = document.querySelectorAll('a[href^="http"]');
for (const link of links) {
const url = link.href;
if (!url) continue;
if (url.includes('yakihonne.com')) continue;
if (url.startsWith('nostr:')) continue;
if (link.closest('.yh-preview-card')) continue;
const key = url + '|' + link.textContent;
if (processed.has(key)) continue;
processed.add(key);
const preview = await fetchPreview(url);
if (!preview) continue;
const card = createCard(preview);
if (!card) continue;
if (
!link.nextElementSibling ||
!link.nextElementSibling.classList.contains('yh-preview-card')
) {
link.insertAdjacentElement('afterend', card);
}
}
}
const observer = new MutationObserver(() => {
clearTimeout(window.__yhPreviewTimer);
window.__yhPreviewTimer = setTimeout(() => {
scanLinks();
}, 500);
});
observer.observe(document.body, {
childList: true,
subtree: true
});
setTimeout(scanLinks, 1500);
setInterval(scanLinks, 3000);
})();
Normalement vous devriez obtenir le résultat suivant :

Write a comment