tech reading time / 4 min
Github readme用のSVG生成をする
GitHubのREADMEに貼るためのSVG生成ツールを作った。
やっていることは単純で、GitHubのユーザー名を渡すと、そのユーザーの公開リポジトリから言語使用量を集計して、言語比率を反映したSVGを返す。 READMEにはusernameをクエリに取ったリンクを普通の画像として貼ることが出来る。

最近まではgithub-readme-statsを使用して言語割合を出していたけど、言語の色を混ぜたら独特のアイコンっぽくなってくれるんじゃないかという興味で実装してみた。
実装はCloudflare Workers上で動くHonoアプリになっている。
エンドポイント/profile.svgでusernameクエリを受け取り、GitHub APIからそのユーザーの公開リポジトリを取得し、各リポジトリのlanguages_urlを辿ることで言語別のbyte数を集計する。
app.get('/profile.svg', async (c) => {
const seed = getRandomSeed()
const username = getUsername(c.req.query('username'))
if (!username) {
return c.text('username query is required', 400)
}
const languageStats = await getLanguageStats(username, c.env.GITHUB_TOKEN)
const svg = createProfileSvg(languageStats, seed)
return c.body(svg, {
headers: {
'content-type': 'image/svg+xml; charset=utf-8',
'cache-control': 'no-store',
},
})
})
SVGの左側には、上位6つの言語色を混ぜた 300pxの正方形を置いている。 中身は本物のcanvasではなくSVGのfilterとpathで作っている。
<filter id="flow" x="-18%" y="-28%" width="136%" height="156%">
<feTurbulence
type="fractalNoise"
baseFrequency="0.009 0.052"
numOctaves="4"
seed="${((seed + 31) % 997) + 1}"
result="flowNoise"
/>
<feDisplacementMap
in="SourceGraphic"
in2="flowNoise"
scale="46"
xChannelSelector="R"
yChannelSelector="B"
/>
</filter>
今のところseedはリクエストごとにランダムなので、アクセスするたびに模様が少し変わるようになっている。