your personal website on atproto - mirror blento.app
at map 90 lines 2.3 kB view raw
1import type { CardDefinition } from '../types'; 2import type GithubContributionsGraph from './GithubContributionsGraph.svelte'; 3import GitHubProfileCard from './GitHubProfileCard.svelte'; 4import type { GitHubContributionsData } from './types'; 5 6export type GithubProfileLoadedData = Record<string, GitHubContributionsData | undefined>; 7 8export const GithubProfileCardDefitition = { 9 type: 'githubProfile', 10 contentComponent: GitHubProfileCard, 11 12 loadData: async (items) => { 13 const githubData: Record<string, GithubContributionsGraph> = {}; 14 for (const item of items) { 15 try { 16 const response = await fetch( 17 `https://blento.app/api/github?user=${encodeURIComponent(item.cardData.user)}` 18 ); 19 if (response.ok) { 20 githubData[item.cardData.user] = await response.json(); 21 } 22 } catch (error) { 23 console.error('Failed to fetch GitHub contributions:', error); 24 } 25 } 26 return githubData; 27 }, 28 onUrlHandler: (url, item) => { 29 const username = getGitHubUsername(url); 30 31 console.log(username); 32 if (!username) return; 33 34 item.cardData.href = url; 35 item.cardData.user = username; 36 37 item.w = 6; 38 item.mobileW = 8; 39 item.h = 3; 40 item.mobileH = 6; 41 return item; 42 }, 43 urlHandlerPriority: 5, 44 minH: 2, 45 minW: 2, 46 47 canChange: (item) => Boolean(getGitHubUsername(item.cardData.href)), 48 change: (item) => { 49 item.cardData.user = getGitHubUsername(item.cardData.href); 50 51 return item; 52 }, 53 name: 'Github Profile' 54} as CardDefinition & { type: 'githubProfile' }; 55 56function getGitHubUsername(url: string | undefined): string | undefined { 57 if (!url) return; 58 59 try { 60 const parsed = new URL(url); 61 62 // Must be github.com (optionally with www.) 63 if (!/^(www\.)?github\.com$/.test(parsed.hostname)) { 64 return undefined; 65 } 66 67 // Remove empty segments 68 const segments = parsed.pathname.split('/').filter(Boolean); 69 70 // Profile URLs have exactly one path segment: /username 71 if (segments.length !== 1) { 72 return undefined; 73 } 74 75 const username = segments[0]; 76 77 // GitHub username rules (simplified but accurate) 78 // - Alphanumeric or hyphens 79 // - Cannot start or end with a hyphen 80 // - Max length 39 81 if (!/^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/.test(username)) { 82 return undefined; 83 } 84 85 return username; 86 } catch { 87 // Invalid URL 88 return undefined; 89 } 90}