diff --git a/quartz/components/Head.tsx b/quartz/components/Head.tsx
index dd4ef25bd..4bca972f7 100644
--- a/quartz/components/Head.tsx
+++ b/quartz/components/Head.tsx
@@ -3,7 +3,7 @@ import { JSResourceToScriptElement } from "../util/resources"
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
import satori from "satori"
import * as fs from "fs"
-import { getTtfFromGfont } from "../util/fonts"
+import { getSatoriFont } from "../util/fonts"
import { GlobalConfiguration } from "../cfg"
import sharp from "sharp"
@@ -12,20 +12,22 @@ import sharp from "sharp"
* @param title what title to use
* @param description what description to use
* @param fileName what fileName to use when writing to disk
- * @param fontName name of font to use (must be google font)
+ * @param headerFontName name of font to use for header (must be google font)
+ * @param bodyFontName name of font to use for body (must be google font)
* @param cfg `GlobalConfiguration` of quartz
*/
async function generateSocialImage(
title: string,
description: string,
fileName: string,
- fontName: string,
+ headerFontName: string,
+ bodyFontName: string,
cfg: GlobalConfiguration,
colorScheme: "lightMode" | "darkMode",
) {
- const font = (await getTtfFromGfont(fontName)) as ArrayBuffer
+ const fonts = await getSatoriFont(headerFontName, bodyFontName)
// How many characters are allowed before switching to smaller font
- const fontBreakPoint = 26
+ const fontBreakPoint = 22
const useSmallerFont = title.length > fontBreakPoint
const svg = await satori(
{
let font: Promise
function Head({ cfg, fileData, externalResources }: QuartzComponentProps) {
if (!font) {
- font = getTtfFromGfont(cfg.theme.typography.header)
+ // font = getSatoriFont(cfg.theme.typography.header)
}
const slug = fileData.filePath
const filePath = slug?.replaceAll("/", "-")
@@ -133,6 +124,7 @@ export default (() => {
description,
filePath as string,
cfg.theme.typography.header,
+ cfg.theme.typography.body,
cfg,
"lightMode",
)
diff --git a/quartz/util/fonts.ts b/quartz/util/fonts.ts
index 77e9df73a..bf5859e18 100644
--- a/quartz/util/fonts.ts
+++ b/quartz/util/fonts.ts
@@ -1,14 +1,38 @@
+import { FontWeight, SatoriOptions } from "satori/wasm"
+
/**
- * Get the `.ttf` file (as ArrayBuffer) of a font by google font name
- * @param font a valid google font
+ * Get an array of `FontOptions` (for satori) given google font names
+ * @param headerFontName name of google font used for header
+ * @param bodyFontName name of google font used for body
+ * @returns FontOptions for header and body
*/
-export async function getTtfFromGfont(font: string) {
- const css = await (await fetch(`https://fonts.googleapis.com/css?family=${font}`)).text()
- const urlRegex = /url\((https:\/\/fonts.gstatic.com\/s\/.*?.ttf)\)/g
- const match = urlRegex.exec(css)
- if (match) {
- // fontData is an ArrayBuffer containing the .ttf file data
- const fontTtf = await (await fetch(match[1])).arrayBuffer()
- return fontTtf
- }
+export async function getSatoriFont(headerFontName: string, bodyFontName: string) {
+ const headerFont = await fetchTtf(headerFontName, 700)
+ const bodyFont = await fetchTtf(bodyFontName, 400)
+
+ const fonts: SatoriOptions["fonts"] = [headerFont, bodyFont]
+ return fonts
}
+
+function fetchTtf(
+ fontName: string,
+ weight: FontWeight,
+): Promise> {
+ return new Promise(async (resolve, reject) => {
+ const css = await (
+ await fetch(`https://fonts.googleapis.com/css?family=${fontName}:${weight}`)
+ ).text()
+ const urlRegex = /url\((https:\/\/fonts.gstatic.com\/s\/.*?.ttf)\)/g
+ const match = urlRegex.exec(css)
+ if (match) {
+ // fontData is an ArrayBuffer containing the .ttf file data
+ const fontTtf = await (await fetch(match[1])).arrayBuffer()
+ resolve({ name: fontName, data: fontTtf, weight: weight as FontWeight, style: "normal" })
+ } else {
+ reject("Could not fetch font")
+ }
+ })
+}
+
+// Type helper
+type GetElementType = T extends (infer U)[] ? U : never