‹ back

tech reading time / 4 min

Github readme用のSVG生成をする

GitHubのREADMEに貼るためのSVG生成ツールを作った。

atolix/langflux atolix/langflux

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

![Language canvas](https://your-worker.example.com/profile.svg?username=<username>)

langflux sample

最近まではgithub-readme-statsを使用して言語割合を出していたけど、言語の色を混ぜたら独特のアイコンっぽくなってくれるんじゃないかという興味で実装してみた。

実装はCloudflare Workers上で動くHonoアプリになっている。 エンドポイント/profile.svgusernameクエリを受け取り、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はリクエストごとにランダムなので、アクセスするたびに模様が少し変わるようになっている。