export interface BadgeLink { href: string | null; label: string; } const safeHttpUrl = (value: string): string | null => { try { const url = new URL(value); return url.protocol === "http:" || url.protocol === "https:" ? value : null; } catch { return null; } }; export const classifySource = (source: string): BadgeLink => { let label = source; const sourceLower = source.toLowerCase(); if (sourceLower.includes("pixiv.net")) { label = "Pixiv"; } else if ( sourceLower.includes("twitter.com") || sourceLower.includes("x.com") ) { label = "X (Twitter)"; } else if (sourceLower.includes("zerochan.net")) { label = "Zerochan"; } else if (sourceLower.includes("imgur.com")) { label = "Imgur"; } else if (sourceLower.includes("lofter.com")) { label = "Lofter"; } return { href: safeHttpUrl(source), label }; }; export const classifyDesigner = (designer: string): BadgeLink => { let name = designer; let userLink = designer; const designerLower = designer.toLowerCase(); const anilistUser = designer.match( /https?:\/\/anilist\.co\/user\/([^/]+)\/?/, ); if (anilistUser) { name = anilistUser[1]; } else if (designerLower.startsWith("@")) { name = designer.replace("@", ""); userLink = `https://anilist.co/user/${name}/`; } else if (!designerLower.startsWith("http")) { userLink = `https://anilist.co/user/${name}/`; } return { href: safeHttpUrl(userLink), label: name }; };