バッジを表示
![](https://coverage.deno.dev/hoge.svg)
バッジを更新
最後の数字を変更することで更新できます。/hoge.svg
などのパスは好きなのいれてください
https://coverage.deno.dev/hoge.svg?97
CI/CDに組み込む場合
vendor/bin/phpunit --coverage-html reports
# for Laravel
# php artisan test --coverage-html reports
percentage=$(printf %.0f $(grep -Pom1 '(?<=aria-valuenow=").*?(?=")' reports/index.html))
curl https://coverage.deno.dev/hoge.svg?$percentage
ソースコード
https://dash.deno.com/_api/projects/ のAPIで環境変数を更新できます。
import { serve } from "https://deno.land/std@0.155.0/http/server.ts";
const seeds = {
width: [107, 3, 4],
cwidth: [29, 3, 4],
x: [915, 15, 20],
textLength: [190, 30, 40]
}
const calc = (p, s) => [s[0], s[1]*2, s[1]*2].slice(0, p.length).reduce((a, b) => a+b)
const thresholds = [97, 93, 80, 65, 45, 15, 0];
const colors = [1217, 9947648, 10790429, 14660375, 16678199, 14703940, 10461087].map(i => i.toString(16));
function generateBadge(p) {
const width = calc(p, seeds.width)
const cwidth = calc(p, seeds.cwidth)
const x = calc(p, seeds.x)
const textLength = calc(p, seeds.textLength)
const color = colors[thresholds.findIndex(i => p >= i)]
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="20" role="img" aria-label="coverage: ${p}%"><title>coverage: ${p}%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="${width}" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="78" height="20" fill="#555"/><rect x="78" width="${cwidth}" height="20" fill="#${color}"/><rect width="${width}" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+"/><text aria-hidden="true" x="485" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="485" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="${x}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${textLength}">${p}%</text><text x="${x}" y="140" transform="scale(.1)" fill="#fff" textLength="${textLength}">${p}%</text></g></svg>`
}
serve(async (req: Request) => {
const url = new URL(req.url)
const p = url.search.slice(1) || Deno.env.get(url.pathname) || '0'
if (url.search) {
fetch('https://dash.deno.com/_api/projects/coverage/env', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'cookie': 'token=' + ACCESS_TOKEN
},
body: JSON.stringify({[url.pathname]: p})
})
}
return new Response(generateBadge(p), {
headers: {
'content-type': 'image/svg+xml; charset=utf-8',
'cache-control': 'private, no-store, no-cache, must-revalidate',
'pragma': 'no-cache'
},
});
});