From d9159e0ac9bfc22e584c78bc8aa04ecd82c14eea Mon Sep 17 00:00:00 2001
From: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Thu, 13 Mar 2025 17:27:46 +0000
Subject: [PATCH] feat: make og images an emitter to properly await image generation (#1826)

---
 quartz/plugins/emitters/componentResources.ts |  111 +++++++++++++++++++++++++------------------------------
 1 files changed, 50 insertions(+), 61 deletions(-)

diff --git a/quartz/plugins/emitters/componentResources.ts b/quartz/plugins/emitters/componentResources.ts
index 7584fdd..d4a3db7 100644
--- a/quartz/plugins/emitters/componentResources.ts
+++ b/quartz/plugins/emitters/componentResources.ts
@@ -9,7 +9,7 @@
 import popoverStyle from "../../components/styles/popover.scss"
 import { BuildCtx } from "../../util/ctx"
 import { QuartzComponent } from "../../components/types"
-import { googleFontHref, joinStyles } from "../../util/theme"
+import { googleFontHref, joinStyles, processGoogleFonts } from "../../util/theme"
 import { Features, transform } from "lightningcss"
 import { transform as transpile } from "esbuild"
 import { write } from "./helpers"
@@ -207,8 +207,7 @@
     async getDependencyGraph(_ctx, _content, _resources) {
       return new DepGraph<FilePath>()
     },
-    async emit(ctx, _content, _resources): Promise<FilePath[]> {
-      const promises: Promise<FilePath>[] = []
+    async *emit(ctx, _content, _resources) {
       const cfg = ctx.cfg.configuration
       // component specific scripts and styles
       const componentResources = getComponentResources(ctx)
@@ -217,42 +216,35 @@
         // let the user do it themselves in css
       } else if (cfg.theme.fontOrigin === "googleFonts" && !cfg.theme.cdnCaching) {
         // when cdnCaching is true, we link to google fonts in Head.tsx
-        let match
+        const response = await fetch(googleFontHref(ctx.cfg.configuration.theme))
+        googleFontsStyleSheet = await response.text()
 
-        const fontSourceRegex = /url\((https:\/\/fonts.gstatic.com\/s\/[^)]+\.(woff2|ttf))\)/g
-
-        googleFontsStyleSheet = await (
-          await fetch(googleFontHref(ctx.cfg.configuration.theme))
-        ).text()
-
-        while ((match = fontSourceRegex.exec(googleFontsStyleSheet)) !== null) {
-          // match[0] is the `url(path)`, match[1] is the `path`
-          const url = match[1]
-          // the static name of this file.
-          const [filename, ext] = url.split("/").pop()!.split(".")
-
-          googleFontsStyleSheet = googleFontsStyleSheet.replace(
-            url,
-            `https://${cfg.baseUrl}/static/fonts/${filename}.ttf`,
+        if (!cfg.baseUrl) {
+          throw new Error(
+            "baseUrl must be defined when using Google Fonts without cfg.theme.cdnCaching",
           )
+        }
 
-          promises.push(
-            fetch(url)
-              .then((res) => {
-                if (!res.ok) {
-                  throw new Error(`Failed to fetch font`)
-                }
-                return res.arrayBuffer()
-              })
-              .then((buf) =>
-                write({
-                  ctx,
-                  slug: joinSegments("static", "fonts", filename) as FullSlug,
-                  ext: `.${ext}`,
-                  content: Buffer.from(buf),
-                }),
-              ),
-          )
+        const { processedStylesheet, fontFiles } = await processGoogleFonts(
+          googleFontsStyleSheet,
+          cfg.baseUrl,
+        )
+        googleFontsStyleSheet = processedStylesheet
+
+        // Download and save font files
+        for (const fontFile of fontFiles) {
+          const res = await fetch(fontFile.url)
+          if (!res.ok) {
+            throw new Error(`failed to fetch font ${fontFile.filename}`)
+          }
+
+          const buf = await res.arrayBuffer()
+          yield write({
+            ctx,
+            slug: joinSegments("static", "fonts", fontFile.filename) as FullSlug,
+            ext: `.${fontFile.extension}`,
+            content: Buffer.from(buf),
+          })
         }
       }
 
@@ -267,45 +259,42 @@
         ...componentResources.css,
         styles,
       )
+
       const [prescript, postscript] = await Promise.all([
         joinScripts(componentResources.beforeDOMLoaded),
         joinScripts(componentResources.afterDOMLoaded),
       ])
 
-      promises.push(
-        write({
-          ctx,
-          slug: "index" as FullSlug,
-          ext: ".css",
-          content: transform({
-            filename: "index.css",
-            code: Buffer.from(stylesheet),
-            minify: true,
-            targets: {
-              safari: (15 << 16) | (6 << 8), // 15.6
-              ios_saf: (15 << 16) | (6 << 8), // 15.6
-              edge: 115 << 16,
-              firefox: 102 << 16,
-              chrome: 109 << 16,
-            },
-            include: Features.MediaQueries,
-          }).code.toString(),
-        }),
-        write({
+      yield write({
+        ctx,
+        slug: "index" as FullSlug,
+        ext: ".css",
+        content: transform({
+          filename: "index.css",
+          code: Buffer.from(stylesheet),
+          minify: true,
+          targets: {
+            safari: (15 << 16) | (6 << 8), // 15.6
+            ios_saf: (15 << 16) | (6 << 8), // 15.6
+            edge: 115 << 16,
+            firefox: 102 << 16,
+            chrome: 109 << 16,
+          },
+          include: Features.MediaQueries,
+        }).code.toString(),
+      }),
+        yield write({
           ctx,
           slug: "prescript" as FullSlug,
           ext: ".js",
           content: prescript,
         }),
-        write({
+        yield write({
           ctx,
           slug: "postscript" as FullSlug,
           ext: ".js",
           content: postscript,
-        }),
-      )
-
-      return await Promise.all(promises)
+        })
     },
   }
 }

--
Gitblit v1.10.0