34 lines
1.2 KiB
TypeScript
34 lines
1.2 KiB
TypeScript
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;
|
|
}
|