@@ -3,38 +3,15 @@ import { useState } from "react";
33import { getDomain } from "tldts" ;
44
55// ---------------------------------------------------------------------------
6- // SourceFavicon — renders the source site's own public favicon .
7- // Do not fetch third-party favicon services here; source URLs may be private .
6+ // SourceFavicon — renders a small favicon derived from a source URL .
7+ // Falls back to a neutral icon if the URL is missing or the image fails to load .
88// ---------------------------------------------------------------------------
99
10- const IPV4_PATTERN = / ^ \d { 1 , 3 } (?: \. \d { 1 , 3 } ) { 3 } $ / ;
11-
12- const isIpHostname = ( hostname : string ) : boolean =>
13- IPV4_PATTERN . test ( hostname ) || hostname . includes ( ":" ) ;
14-
1510export function sourceFaviconUrl ( url : string | undefined , size : number ) : string | null {
1611 if ( ! url ) return null ;
17- if ( ! URL . canParse ( url ) ) return null ;
18-
19- const parsed = new URL ( url ) ;
20- if ( parsed . protocol !== "https:" && parsed . protocol !== "http:" ) return null ;
21-
22- const hostname = parsed . hostname . toLowerCase ( ) ;
23- if (
24- hostname === "localhost" ||
25- hostname . endsWith ( ".localhost" ) ||
26- hostname . endsWith ( ".local" ) ||
27- isIpHostname ( hostname )
28- ) {
29- return null ;
30- }
31-
32- const domain = getDomain ( hostname ) ;
12+ const domain = getDomain ( url ) ?? ( URL . canParse ( url ) ? getDomain ( new URL ( url ) . hostname ) : null ) ;
3313 if ( ! domain ) return null ;
34-
35- const favicon = new URL ( `https://${ domain } /favicon.ico` ) ;
36- favicon . searchParams . set ( "sz" , String ( size * 2 ) ) ;
37- return favicon . toString ( ) ;
14+ return `https://www.google.com/s2/favicons?domain=${ domain } &sz=${ size * 2 } ` ;
3815}
3916
4017export function SourceFavicon ( { url, size = 16 } : { url ?: string ; size ?: number } ) {
0 commit comments