Public
HTTP
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

SVG Button Link for Markdown

Pioneered by @easrng, this val allows you to create an SVG image via the Express API, which we can embed in Val Town markdown, and wrap so it acts like a button.

Usage

[![Button Link](https://stevekrouse-button.web.val.run/Button%20Link)](https://example.com)

Button Link

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
49
50
51
52
53
54
55
56
57
import { fetch } from "https://esm.town/v/std/fetch";
export default async function server(req: Request): Promise<Response> {
async function inlineUrls(cssString: string) {
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(String.fromCharCode.apply(null, data))
}")`,
);
}
return result;
}
const esc = (await import("https://esm.sh/escape-html@1.0.3")).default;
const { init } = await import("https://esm.sh/server-text-width@1.0.2");
const { getTextWidth } = init(
(await import("https://easrng.github.io/IBMPlexSansMetrics.js")).default,
);
const url = new URL(req.url);
const text = decodeURIComponent(url.pathname.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.headers.get("user-agent") || "" } },
);
if (!r.ok)
throw new Error("Failed to fetch font CSS");
fontCss = await inlineUrls(await r.text());
}
catch (e) {
console.error("Error fetching font CSS:", e);
}
const width = Math.ceil(getTextWidth(text) + 16);
const svgContent = `<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-fami
esc(text)
}</span></foreignObject></svg>`;
return new Response(svgContent, {
headers: {
"content-type": "image/svg+xml",
},
});
}
// Forked from @easrng.button
stevekrouse-button.web.val.run
September 4, 2024