const LEGACY_ICON_FILENAME_PATTERN = /^[a-z0-9][a-z0-9._-]*\.svg$/i; const CLOUDINARY_SPORT_ICON_PATH_PATTERN = /\/image\/upload\/(?:v\d+\/)?sports-icons\/[^/?#]+\.svg(?:[?#].*)?$/i; export function resolveSportIconUrl(iconUrl: string | null | undefined): string | null { if (!iconUrl) return null; if (/^(https?:|data:|\/)/.test(iconUrl)) return iconUrl; return `/sports-icons/${iconUrl}`; } export function isCloudinarySportIconUrl(iconUrl: string): boolean { try { const url = new URL(iconUrl); return url.protocol === "https:" && url.hostname.endsWith("res.cloudinary.com") && CLOUDINARY_SPORT_ICON_PATH_PATTERN.test(`${url.pathname}${url.search}${url.hash}`); } catch { return false; } } export function isLegacySportIconFilename(iconUrl: string): boolean { return LEGACY_ICON_FILENAME_PATTERN.test(iconUrl) && !iconUrl.includes("/"); } export function parseSportIconUrlInput(value: unknown): string | null | undefined { if (typeof value !== "string" || !value.trim()) return null; const iconUrl = value.trim(); if (isCloudinarySportIconUrl(iconUrl) || isLegacySportIconFilename(iconUrl)) { return iconUrl; } return undefined; }