refactor(downloadFont): handle generic families and multi-family strings
Strips generic CSS families (serif, monospace, etc.) before building the font API URL, and correctly parses comma-separated font stacks.
This commit is contained in:
@@ -1,33 +1,48 @@
|
|||||||
import FontFaceObserver from "fontfaceobserver"
|
import FontFaceObserver from "fontfaceobserver"
|
||||||
|
|
||||||
const assembleFontLink = (font: string) => {
|
const GENERIC_FAMILIES = new Set([
|
||||||
return `https://api.fonts.coollabs.io/css2?display=swap&family=${font
|
"serif", "sans-serif", "monospace", "cursive", "fantasy",
|
||||||
.replaceAll(",", "&family=")
|
"system-ui", "ui-serif", "ui-sans-serif", "ui-monospace", "ui-rounded",
|
||||||
.replaceAll(" ", "+")}`
|
])
|
||||||
|
|
||||||
|
const parseWebFontFamilies = (font: string): string[] =>
|
||||||
|
font
|
||||||
|
.split(",")
|
||||||
|
.map(f => f.trim().replace(/^["']|["']$/g, ""))
|
||||||
|
.filter(f => f && !GENERIC_FAMILIES.has(f))
|
||||||
|
|
||||||
|
const assembleFontLink = (families: string[]): string | null => {
|
||||||
|
if (families.length === 0) return null
|
||||||
|
return `https://api.fonts.coollabs.io/css2?display=swap&${
|
||||||
|
families.map(f => `family=${f.replaceAll(" ", "+")}`).join("&")
|
||||||
|
}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const downloadFont = async (
|
export const downloadFont = async (
|
||||||
font: string,
|
font: string,
|
||||||
cssVar = "--font-family"
|
cssVar = "--font-family"
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const href = assembleFontLink(font)
|
const families = parseWebFontFamilies(font)
|
||||||
|
const href = assembleFontLink(families)
|
||||||
|
|
||||||
// check if the href already exists
|
if (href) {
|
||||||
const existingLink = document.querySelector(`link[href="${href}"]`)
|
const alreadyLoaded = Array.from(
|
||||||
|
document.head.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]')
|
||||||
|
).some(link => link.href === href)
|
||||||
|
|
||||||
if (!existingLink) {
|
if (!alreadyLoaded) {
|
||||||
const link = document.createElement("link")
|
const link = document.createElement("link")
|
||||||
link.href = href
|
link.href = href
|
||||||
link.rel = "stylesheet"
|
link.rel = "stylesheet"
|
||||||
|
document.head.appendChild(link)
|
||||||
|
}
|
||||||
|
|
||||||
document.head.appendChild(link)
|
try {
|
||||||
|
await new FontFaceObserver(families[0]).load()
|
||||||
|
} catch {
|
||||||
|
console.warn("error when loading font")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
document.documentElement.style.setProperty(cssVar, font)
|
||||||
await new FontFaceObserver(font).load()
|
|
||||||
|
|
||||||
document.documentElement.style.setProperty(cssVar, font)
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("error when loading font")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user