From 6e54811aa55f4e45ccf968824a23181aeab3584d Mon Sep 17 00:00:00 2001 From: Jiji Date: Wed, 28 May 2025 22:29:40 +0900 Subject: [PATCH 1/2] feat: add top-languages.ts to utils --- .../pixel-profile/src/utils/top-languages.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 packages/pixel-profile/src/utils/top-languages.ts diff --git a/packages/pixel-profile/src/utils/top-languages.ts b/packages/pixel-profile/src/utils/top-languages.ts new file mode 100644 index 0000000..c03323b --- /dev/null +++ b/packages/pixel-profile/src/utils/top-languages.ts @@ -0,0 +1,24 @@ +import axios from 'axios' + +export async function getTopLanguages(username: string, token?: string): Promise { + const headers = token ? { Authorization: `token ${token}` } : {} + const reposRes = await axios.get(`https://api.github.com/users/${username}/repos?per_page=100`, { headers }) + const repos = reposRes.data + + const languageStats: Record = {} + + for (const repo of repos) { + if (repo.fork) continue + const langRes = await axios.get(repo.languages_url, { headers }) + const langs = langRes.data + for (const [lang, bytes] of Object.entries(langs)) { + languageStats[lang] = (languageStats[lang] || 0) + (bytes as number) + } + } + + const sorted = Object.entries(languageStats).sort((a, b) => b[1] - a[1]) + const top3 = sorted.slice(0, 3) + const total = top3.reduce((sum, [, bytes]) => sum + bytes, 0) + + return top3.map(([lang, bytes]) => `${lang} ${Math.round((bytes / total) * 100)}%`).join(', ') +} From 10b2eeaafa7c9de2dc78a6f7a2ff14e7a13041da Mon Sep 17 00:00:00 2001 From: Jiji Date: Fri, 30 May 2025 12:01:02 +0900 Subject: [PATCH 2/2] feat(top languages): add top languages stat --- packages/pixel-profile/src/cards/stats.ts | 6 ++++++ .../src/templates/github-stats.tsx | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/pixel-profile/src/cards/stats.ts b/packages/pixel-profile/src/cards/stats.ts index 4a16bbc..c394ae1 100644 --- a/packages/pixel-profile/src/cards/stats.ts +++ b/packages/pixel-profile/src/cards/stats.ts @@ -13,6 +13,7 @@ import { getThemeOptions } from '../theme' import { getBase64FromPixels, getPixelsFromPngBuffer, getPngBufferFromPixels, kFormatter, Rank } from '../utils' import { getPngBufferFromURL } from '../utils/converter' import { filterNotEmpty } from '../utils/filter' +import { getTopLanguages } from '../utils/top-languages' // import top-languages import { fontBuffer } from './PressStart2P-Regular' import { Resvg } from '@resvg/resvg-js' import satori from 'satori' @@ -20,6 +21,7 @@ import satori from 'satori' export type Stats = { name: string username: string + topLanguages: string // add top languages stat totalStars: number totalCommits: number totalIssues: number @@ -60,6 +62,9 @@ export async function renderStats(stats: Stats, options: Options = {}): Promise< dithering = false } = options + const token = process.env.PAT_1 || '' // add token for topLanguages + const topLanguages = await getTopLanguages(username, token) // add const topLanguages + const applyAvatarBorder = avatarBorder !== undefined ? avatarBorder : theme !== '' if (hiddenStatsKeys.includes('avatar')) { @@ -76,6 +81,7 @@ export async function renderStats(stats: Stats, options: Options = {}): Promise< const _stats = { name, avatar, + topLanguages, // add top languages to _stats stars: kFormatter(totalStars), commits: kFormatter(totalCommits), issues: kFormatter(totalIssues), diff --git a/packages/pixel-profile/src/templates/github-stats.tsx b/packages/pixel-profile/src/templates/github-stats.tsx index bac4043..50f1ea5 100644 --- a/packages/pixel-profile/src/templates/github-stats.tsx +++ b/packages/pixel-profile/src/templates/github-stats.tsx @@ -10,6 +10,7 @@ export type Stats = { prs: string rank: Rank['level'] stars: string + topLanguages: string // add top languages stat } export type TemplateOptions = { @@ -43,7 +44,7 @@ export const AVATAR_SIZE = { AVATAR_HEIGHT: 280 } -const mainStatsItems = ['stars', 'commits', 'issues', 'prs', 'contributions'] +const mainStatsItems = ['stars', 'commits', 'issues', 'prs', 'contributions', 'topLanguages'] // add top languages const getVisibleMainStatsCount = (hiddenStatsKeys: string[]) => mainStatsItems.filter((stat) => !hiddenStatsKeys.includes(stat)).length @@ -110,6 +111,22 @@ export function makeGithubStats(stats: Stats, options: TemplateOptions) { paddingRight: avatar ? 40 : 0 }} > + {isVisible('topLanguages') && ( +
+
Top Languages:
+
{stats.topLanguages}
+
+ )} {isVisible('stars') && (