Don't fall back to a favicon for image-less tweets

resolveHeroImage's favicon fallback exists so regular articles never look
entirely bare, but for a tweet it meant an image-less tweet showed the
Nitter instance's own favicon slapped on as if it were the tweet's photo.
publishDirect now skips that fallback specifically for tweet items —
TweetCard.svelte already renders cleanly with no image at all.
This commit is contained in:
Claude
2026-07-22 22:17:44 +00:00
parent bc6e75c124
commit 8cc256f27d
+11 -3
View File
@@ -35,11 +35,15 @@ function deriveTitle(body: string): string {
/**
* Resolves the hero image for an article: try the best candidate from the source
* items, download and locally host it; if there isn't one, fall back to the site's
* favicon rather than leaving the article with no art at all.
* favicon rather than leaving the article with no art at all. That favicon fallback
* is skipped for tweets (allowFaviconFallback: false) — a Nitter instance's own
* favicon slapped onto an image-less tweet reads as a mistake, not a placeholder;
* TweetCard.svelte already handles no-image tweets gracefully with no image at all.
*/
async function resolveHeroImage(
items: ContentItem[],
primaryLink: string
primaryLink: string,
allowFaviconFallback = true
): Promise<{ heroImage: MergedArticle['heroImage']; storedMediaId: string | null }> {
const selected = selectBestImage(items);
@@ -55,6 +59,10 @@ async function resolveHeroImage(
return { heroImage: selected, storedMediaId: null };
}
if (!allowFaviconFallback) {
return { heroImage: null, storedMediaId: null };
}
const favicon = faviconUrlFor(primaryLink);
if (favicon) {
const stored = await downloadAndStore(favicon, 'published', {});
@@ -81,7 +89,7 @@ async function resolveHeroImage(
*/
export async function publishDirect(item: ContentItem): Promise<MergedArticle> {
const category = uniqueCategories([item]);
const { heroImage, storedMediaId } = await resolveHeroImage([item], item.link);
const { heroImage, storedMediaId } = await resolveHeroImage([item], item.link, !item.tweet);
const video = item.videos[0]
? { url: item.videos[0].url, provider: item.videos[0].provider, embedUrl: item.videos[0].embedHtml, sourceItemId: item.id }
: null;