Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import { fetch } from "https://esm.town/v/std/fetch";
export async function badge(req, res) {
async function inlineUrls(cssString) {
const urlRegex = /url\(['"]?(.*?)['"]?\)/g;
let result = cssString;
for (const urlMatch of cssString.matchAll(urlRegex)) {
const originalUrl = urlMatch[1];
const response = await fetch(originalUrl);
const data = new Uint8Array(await response.arrayBuffer());
result = result.replace(
urlMatch[0],
`url("data:${response.headers.get("content-type")};base64,${
btoa(data.reduce((a, b) => a + String.fromCharCode(b), ""))
}")`,
);
}
return result;
}
const esc = (await import("npm:escape-html@1.0.3")).default;
const { init } = await import("npm:server-text-width@1.0.2");
const { getTextWidth } = init(
(await import("https://easrng.github.io/IBMPlexSansMetrics.js")).default,
);
const text = decodeURIComponent(req.path.split("/")[1]);
let fontCss = "";
try {
const r = await fetch(
"https://fonts.googleapis.com/css2?family=" +
encodeURIComponent("IBM Plex Sans:wght@600") +
"&text=" +
encodeURIComponent(text),
{ headers: { "user-agent": req.get("user-agent") } },
);
if (!r.ok)
throw new Error();
fontCss = await inlineUrls(await r.text());
}
catch (e) {}
res.set("content-type", "image/svg+xml");
const width = Math.ceil(getTextWidth(text) + 16);
res.end(
`<svg viewBox="0 0 ${width} 28" width="${width}" height="28" xmlns="http://www.w3.org/2000/svg"><defs><style>${fontCss}</style></defs><foreignObject width="100%" height="100%"><span xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'IBM Plex Sans';font-weight: 600;font-size: .875rem;line-height: 1.25rem;padding-top: .25rem;padding-bottom: .25rem;padding-left: .5rem;padding-right: .5rem;display: inline-block;background: rgb(59 130 246);color: #fff;border-radius: .25rem;text-align: center;">${
esc(text)
}</span></foreignObject></svg>`,
);
}
// Forked from @easrng.button