From 5b13ff21992a61eb8b03670ae1742a72703c2afe Mon Sep 17 00:00:00 2001
From: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Thu, 06 Mar 2025 02:16:24 +0000
Subject: [PATCH] feat: support emitters defining external resources, emit link from contentindex directly

---
 quartz/plugins/types.ts                  |    4 +++-
 quartz/util/resources.tsx                |    2 ++
 quartz/plugins/emitters/contentIndex.tsx |   14 ++++++++++++++
 quartz/plugins/transformers/latex.ts     |    2 --
 quartz/plugins/index.ts                  |    6 +++++-
 quartz/components/renderPage.tsx         |    1 +
 quartz/components/Head.tsx               |   11 +++++++++--
 docs/advanced/making plugins.md          |    2 --
 8 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/docs/advanced/making plugins.md b/docs/advanced/making plugins.md
index 3042737..8ed533f 100644
--- a/docs/advanced/making plugins.md
+++ b/docs/advanced/making plugins.md
@@ -99,8 +99,6 @@
             },
           ],
         }
-      } else {
-        return {}
       }
     },
   }
diff --git a/quartz/components/Head.tsx b/quartz/components/Head.tsx
index a1fb0f6..09156c9 100644
--- a/quartz/components/Head.tsx
+++ b/quartz/components/Head.tsx
@@ -127,7 +127,7 @@
       }
     }
 
-    const { css, js } = externalResources
+    const { css, js, additionalHead } = externalResources
 
     const url = new URL(`https://${cfg.baseUrl ?? "example.com"}`)
     const path = url.pathname as FullSlug
@@ -177,7 +177,7 @@
             <link rel="stylesheet" href={googleFontHref(cfg.theme)} />
           </>
         )}
-        <link rel="preconnect" href="https://cdnjs.cloudflare.com" crossOrigin={"anonymous"} />
+        <link rel="preconnect" href="https://cdnjs.cloudflare.com" crossOrigin="anonymous" />
         <meta name="viewport" content="width=device-width, initial-scale=1.0" />
         {/* OG/Twitter meta tags */}
         <meta name="og:site_name" content={cfg.pageTitle}></meta>
@@ -213,6 +213,13 @@
         {js
           .filter((resource) => resource.loadTime === "beforeDOMReady")
           .map((res) => JSResourceToScriptElement(res, true))}
+        {additionalHead.map((resource) => {
+          if (typeof resource === "function") {
+            return resource(fileData)
+          } else {
+            return resource
+          }
+        })}
       </head>
     )
   }
diff --git a/quartz/components/renderPage.tsx b/quartz/components/renderPage.tsx
index 3914411..9cebaa8 100644
--- a/quartz/components/renderPage.tsx
+++ b/quartz/components/renderPage.tsx
@@ -54,6 +54,7 @@
       },
       ...staticResources.js,
     ],
+    additionalHead: staticResources.additionalHead,
   }
 
   if (fileData.hasMermaidDiagram) {
diff --git a/quartz/plugins/emitters/contentIndex.ts b/quartz/plugins/emitters/contentIndex.tsx
similarity index 93%
rename from quartz/plugins/emitters/contentIndex.ts
rename to quartz/plugins/emitters/contentIndex.tsx
index 5d76e08..bd609b4 100644
--- a/quartz/plugins/emitters/contentIndex.ts
+++ b/quartz/plugins/emitters/contentIndex.tsx
@@ -182,6 +182,20 @@
 
       return emitted
     },
+    externalResources: (ctx) => {
+      if (opts?.enableRSS) {
+        return {
+          additionalHead: [
+            <link
+              rel="alternate"
+              type="application/rss+xml"
+              title="RSS Feed"
+              href={`https://${ctx.cfg.configuration.baseUrl}/index.xml`}
+            />,
+          ],
+        }
+      }
+    },
     getQuartzComponents: () => [],
   }
 }
diff --git a/quartz/plugins/index.ts b/quartz/plugins/index.ts
index df9fd1d..c41157c 100644
--- a/quartz/plugins/index.ts
+++ b/quartz/plugins/index.ts
@@ -6,9 +6,10 @@
   const staticResources: StaticResources = {
     css: [],
     js: [],
+    additionalHead: [],
   }
 
-  for (const transformer of ctx.cfg.plugins.transformers) {
+  for (const transformer of [...ctx.cfg.plugins.transformers, ...ctx.cfg.plugins.emitters]) {
     const res = transformer.externalResources ? transformer.externalResources(ctx) : {}
     if (res?.js) {
       staticResources.js.push(...res.js)
@@ -16,6 +17,9 @@
     if (res?.css) {
       staticResources.css.push(...res.css)
     }
+    if (res?.additionalHead) {
+      staticResources.additionalHead.push(...res.additionalHead)
+    }
   }
 
   // if serving locally, listen for rebuilds and reload the page
diff --git a/quartz/plugins/transformers/latex.ts b/quartz/plugins/transformers/latex.ts
index 26913ba..40939d5 100644
--- a/quartz/plugins/transformers/latex.ts
+++ b/quartz/plugins/transformers/latex.ts
@@ -59,8 +59,6 @@
               },
             ],
           }
-        default:
-          return { css: [], js: [] }
       }
     },
   }
diff --git a/quartz/plugins/types.ts b/quartz/plugins/types.ts
index 667799f..283a999 100644
--- a/quartz/plugins/types.ts
+++ b/quartz/plugins/types.ts
@@ -13,6 +13,7 @@
 }
 
 type OptionType = object | undefined
+type ExternalResourcesFn = (ctx: BuildCtx) => Partial<StaticResources> | undefined
 export type QuartzTransformerPlugin<Options extends OptionType = undefined> = (
   opts?: Options,
 ) => QuartzTransformerPluginInstance
@@ -21,7 +22,7 @@
   textTransform?: (ctx: BuildCtx, src: string) => string
   markdownPlugins?: (ctx: BuildCtx) => PluggableList
   htmlPlugins?: (ctx: BuildCtx) => PluggableList
-  externalResources?: (ctx: BuildCtx) => Partial<StaticResources>
+  externalResources?: ExternalResourcesFn
 }
 
 export type QuartzFilterPlugin<Options extends OptionType = undefined> = (
@@ -44,4 +45,5 @@
     content: ProcessedContent[],
     resources: StaticResources,
   ): Promise<DepGraph<FilePath>>
+  externalResources?: ExternalResourcesFn
 }
diff --git a/quartz/util/resources.tsx b/quartz/util/resources.tsx
index 72ae9e6..2ec8561 100644
--- a/quartz/util/resources.tsx
+++ b/quartz/util/resources.tsx
@@ -1,5 +1,6 @@
 import { randomUUID } from "crypto"
 import { JSX } from "preact/jsx-runtime"
+import { QuartzPluginData } from "../plugins/vfile"
 
 export type JSResource = {
   loadTime: "beforeDOMReady" | "afterDOMReady"
@@ -62,4 +63,5 @@
 export interface StaticResources {
   css: CSSResource[]
   js: JSResource[]
+  additionalHead: (JSX.Element | ((pageData: QuartzPluginData) => JSX.Element))[]
 }

--
Gitblit v1.10.0