From 314a88d5c607c3f0cdef6706e4bf84590d60f311 Mon Sep 17 00:00:00 2001
From: Emile Bangma <github@emilebangma.com>
Date: Wed, 30 Oct 2024 22:57:39 +0000
Subject: [PATCH] feat(transformer): allow inline CSS styling (#1551)

---
 quartz/util/resources.tsx            |   25 ++++++++++++++++++++++++-
 quartz/plugins/transformers/latex.ts |    6 ++++--
 quartz/components/renderPage.tsx     |    7 ++++++-
 quartz/components/Head.tsx           |    6 ++----
 docs/advanced/making plugins.md      |    8 +++++---
 5 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/docs/advanced/making plugins.md b/docs/advanced/making plugins.md
index 0ba2968..9925d16 100644
--- a/docs/advanced/making plugins.md
+++ b/docs/advanced/making plugins.md
@@ -27,7 +27,7 @@
   - `cfg`: The full Quartz [[configuration]]
   - `allSlugs`: a list of all the valid content slugs (see [[paths]] for more information on what a `ServerSlug` is)
 - `StaticResources` is defined in `quartz/resources.tsx`. It consists of
-  - `css`: a list of URLs for stylesheets that should be loaded
+  - `css`: a list of CSS style definitions that should be loaded. A CSS style is described with the `CSSResource` type which is also defined in `quartz/resources.tsx`. It accepts either a source URL or the inline content of the stylesheet.
   - `js`: a list of scripts that should be loaded. A script is described with the `JSResource` type which is also defined in `quartz/resources.tsx`. It allows you to define a load time (either before or after the DOM has been loaded), whether it should be a module, and either the source URL or the inline content of the script.
 
 ## Transformers
@@ -85,8 +85,10 @@
       if (engine === "katex") {
         return {
           css: [
-            // base css
-            "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css",
+            {
+              // base css
+              content: "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css",
+            },
           ],
           js: [
             {
diff --git a/quartz/components/Head.tsx b/quartz/components/Head.tsx
index 90e3387..cf79434 100644
--- a/quartz/components/Head.tsx
+++ b/quartz/components/Head.tsx
@@ -1,6 +1,6 @@
 import { i18n } from "../i18n"
 import { FullSlug, joinSegments, pathToRoot } from "../util/path"
-import { JSResourceToScriptElement } from "../util/resources"
+import { CSSResourceToStyleElement, JSResourceToScriptElement } from "../util/resources"
 import { googleFontHref } from "../util/theme"
 import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
 
@@ -40,9 +40,7 @@
         <link rel="icon" href={iconPath} />
         <meta name="description" content={description} />
         <meta name="generator" content="Quartz" />
-        {css.map((href) => (
-          <link key={href} href={href} rel="stylesheet" type="text/css" spa-preserve />
-        ))}
+        {css.map((resource) => CSSResourceToStyleElement(resource, true))}
         {js
           .filter((resource) => resource.loadTime === "beforeDOMReady")
           .map((res) => JSResourceToScriptElement(res, true))}
diff --git a/quartz/components/renderPage.tsx b/quartz/components/renderPage.tsx
index f2dccea..9c53096 100644
--- a/quartz/components/renderPage.tsx
+++ b/quartz/components/renderPage.tsx
@@ -29,7 +29,12 @@
   const contentIndexScript = `const fetchData = fetch("${contentIndexPath}").then(data => data.json())`
 
   return {
-    css: [joinSegments(baseDir, "index.css"), ...staticResources.css],
+    css: [
+      {
+        content: joinSegments(baseDir, "index.css"),
+      },
+      ...staticResources.css,
+    ],
     js: [
       {
         src: joinSegments(baseDir, "prescript.js"),
diff --git a/quartz/plugins/transformers/latex.ts b/quartz/plugins/transformers/latex.ts
index 28b4d50..d323b3e 100644
--- a/quartz/plugins/transformers/latex.ts
+++ b/quartz/plugins/transformers/latex.ts
@@ -31,8 +31,10 @@
       if (engine === "katex") {
         return {
           css: [
-            // base css
-            "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css",
+            {
+              // base css
+              content: "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css",
+            },
           ],
           js: [
             {
diff --git a/quartz/util/resources.tsx b/quartz/util/resources.tsx
index a572d89..72ae9e6 100644
--- a/quartz/util/resources.tsx
+++ b/quartz/util/resources.tsx
@@ -16,6 +16,12 @@
     }
 )
 
+export type CSSResource = {
+  content: string
+  inline?: boolean
+  spaPreserve?: boolean
+}
+
 export function JSResourceToScriptElement(resource: JSResource, preserve?: boolean): JSX.Element {
   const scriptType = resource.moduleType ?? "application/javascript"
   const spaPreserve = preserve ?? resource.spaPreserve
@@ -36,7 +42,24 @@
   }
 }
 
+export function CSSResourceToStyleElement(resource: CSSResource, preserve?: boolean): JSX.Element {
+  const spaPreserve = preserve ?? resource.spaPreserve
+  if (resource.inline ?? false) {
+    return <style>{resource.content}</style>
+  } else {
+    return (
+      <link
+        key={resource.content}
+        href={resource.content}
+        rel="stylesheet"
+        type="text/css"
+        spa-preserve={spaPreserve}
+      />
+    )
+  }
+}
+
 export interface StaticResources {
-  css: string[]
+  css: CSSResource[]
   js: JSResource[]
 }

--
Gitblit v1.10.0