const icons: Record = { none: 'material-symbols:link', 'steamcommunity.com': 'simple-icons:steam', 'twitter.com': 'simple-icons:x', 'x.com': 'simple-icons:x', 'github.com': 'simple-icons:github', 'youtube.com': 'simple-icons:youtube', 'itch.io': 'simple-icons:itchdotio', 'discord.gg': 'simple-icons:discord', 'gamebanana.com': 'simple-icons:gamebanana', 'bsky.app': 'simple-icons:bluesky', 'bsky.social': 'simple-icons:bluesky', // https://хамяк.рф 'xn--80auf8a2c.xn--p1ai': 'fluent-emoji-high-contrast:hamster', 'teasanctuary.ru': '/icons/tea-sanctuary-white.svg', 'hl.teasanctuary.ru': '/icons/half-life.svg', 'git.teasanctuary.ru': 'devicon-plain:git', localhost: '/icons/tea-sanctuary-white.svg', email: 'material-symbols:alternate-email' }; // Особые случаи, когда одним доменом второго уровня не ограничишься (например, randomtrash.itch.io) const specialResolvers: Record string> = { 'teasanctuary.ru': (url) => { // Домены третьего уровня и выше const prefix = url.hostname.split('.').toReversed(); prefix.shift(); prefix.shift(); if (prefix[0] === "hl") { return 'hl.teasanctuary.ru'; } if (prefix[0] === "git" || url.pathname.split('/')[1] == "git") { return 'git.teasanctuary.ru'; } return 'teasanctuary.ru'; }, // Игнорируем имя пользователя 'bsky.app': (url) => 'bsky.app', 'bsky.social': (url) => 'bsky.social', 'itch.io': (url) => 'itch.io' } function getIconFromUrl(url: URL): string | undefined { const href = url.href; if (href.startsWith('mailto:')) return 'email'; const hostname = url.hostname; const secondLevel = hostname.match(/(([A-Za-z0-9\-])+\.([A-Za-z0-9\-])+)$/)?.at(0) ?? ''; if (specialResolvers[secondLevel]) return icons[specialResolvers[secondLevel](url)]; return icons[hostname]; } export function tryGetIcon(link: string): string { let url: URL; try { url = new URL(link); } catch { return icons['none']; } return getIconFromUrl(url) ?? icons['none']; } /** * Проверка на "локальность" ссылки - принадлежность её этому сайту. Используется, например, * в социальных ссылках, чтобы не открывать новую вкладку для страниц сайта. * @param link Локальная либо глобальная ссылка * @returns true, если ссылка не ведёт за пределы сайта */ export function isLinkLocal(link: string): boolean { let url: URL; try { url = new URL(link); } catch { return true; } // Поддомены teasanctuary.ru должны всегда быть "внешними" return url.hostname === "" || url.hostname === "teasanctuary.ru"; }