brackt/app/lib/sport-icon-url.ts

35 lines
1.2 KiB
TypeScript
Raw Normal View History

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;
}