Skip to content

Commit de97589

Browse files
authored
Deprioritize ICO files in favicon selection (#2188)
1 parent bb4b9d5 commit de97589

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

src/lib/utils/favicon.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,25 @@ async function fetchBasicMetadata(url: string): Promise<{
172172

173173
// Try to extract high-quality icons in order of preference
174174
// Data URLs (base64 encoded) are now supported
175+
// Note: ICO files are deprioritized because they often contain only BMP data
176+
// which is harder to process than PNG/SVG formats
175177
const candidateIcons: string[] = [];
176178

179+
// Helper to check if URL points to an ICO file
180+
const isIcoFile = (url: string): boolean => {
181+
try {
182+
const pathname = new URL(url, "http://example.com").pathname.toLowerCase();
183+
return pathname.endsWith(".ico");
184+
} catch {
185+
return url.toLowerCase().endsWith(".ico");
186+
}
187+
};
188+
177189
// 1. Apple touch icon (usually highest quality, 180x180 or similar)
190+
// Skip if it's an ICO file - these often don't contain extractable PNG data
178191
const appleIcon =
179192
extractLinkHref("apple-touch-icon") || extractLinkHref("apple-touch-icon-precomposed");
180-
if (appleIcon) candidateIcons.push(appleIcon);
193+
if (appleIcon && !isIcoFile(appleIcon)) candidateIcons.push(appleIcon);
181194

182195
// 2. High-res icon with sizes attribute
183196
const highResIcon = headContent.match(
@@ -201,12 +214,16 @@ async function fetchBasicMetadata(url: string): Promise<{
201214
}
202215
}
203216

204-
// 4. Any icon or shortcut icon
217+
// 4. Any icon or shortcut icon (prefer non-ICO)
205218
const standardIcon =
206219
extractLinkHref("icon") || extractLinkHref("shortcut icon") || extractLinkHref("shortcut");
207-
if (standardIcon) candidateIcons.push(standardIcon);
220+
if (standardIcon && !isIcoFile(standardIcon)) candidateIcons.push(standardIcon);
221+
222+
// 5. ICO files as lower priority fallback (may not have extractable PNG data)
223+
if (appleIcon && isIcoFile(appleIcon)) candidateIcons.push(appleIcon);
224+
if (standardIcon && isIcoFile(standardIcon)) candidateIcons.push(standardIcon);
208225

209-
// 5. OG image as last resort (sometimes sites use their logo as og:image)
226+
// 6. OG image as last resort (sometimes sites use their logo as og:image)
210227
if (ogImage && ogImage.includes("logo")) {
211228
candidateIcons.push(ogImage);
212229
}

0 commit comments

Comments
 (0)