45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
/**
|
|
* Twemoji glyphs, fetched from the jsDelivr CDN.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
/** The pinned Twemoji release. */
|
|
const TWEMOJI_VERSION = "16.0.1";
|
|
|
|
/** Fetched glyphs by codepoint, so repeated runs don't re-hit the network. */
|
|
const glyphCache = new Map<string, string>();
|
|
|
|
/**
|
|
* Fetches Twemoji's plain vector-path SVG for `emoji`, whose file is named
|
|
* `cp` (see `emojiToCodepoint` in lib/site-icons.ts).
|
|
*
|
|
* @throws {Error} When the glyph can't be fetched.
|
|
*/
|
|
export async function fetchTwemojiSvg(
|
|
emoji: string,
|
|
cp: string,
|
|
): Promise<string> {
|
|
const cached = glyphCache.get(cp);
|
|
if (cached) return cached;
|
|
const url =
|
|
`https://cdn.jsdelivr.net/gh/jdecked/twemoji@${TWEMOJI_VERSION}/assets/svg/${cp}.svg`;
|
|
let res: Response;
|
|
try {
|
|
res = await fetch(url);
|
|
} catch (cause) {
|
|
throw new Error(
|
|
`Failed to fetch Twemoji glyph for "${emoji}" (${cp}) from ${url}`,
|
|
{ cause },
|
|
);
|
|
}
|
|
if (!res.ok) {
|
|
throw new Error(
|
|
`Failed to fetch Twemoji glyph for "${emoji}" (${cp}) from ${url}: ${res.status} ${res.statusText}`,
|
|
);
|
|
}
|
|
const svg = await res.text();
|
|
glyphCache.set(cp, svg);
|
|
return svg;
|
|
}
|