From 25979ab216ca2cc2539696420f23be8508d3184f Mon Sep 17 00:00:00 2001
From: Felix Nie <hongtuo.nie@u.nus.edu>
Date: Wed, 19 Mar 2025 04:43:32 +0000
Subject: [PATCH] feat(fonts): allow PageTitle to have its own font subset (#1848)
---
quartz/util/theme.ts | 18 +++++++++++++++---
quartz/plugins/emitters/componentResources.ts | 16 ++++++++++++++--
docs/configuration.md | 9 +++++----
quartz/components/PageTitle.tsx | 1 +
quartz/components/Head.tsx | 5 ++++-
5 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/docs/configuration.md b/docs/configuration.md
index e29dc80..4026c51 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -41,11 +41,12 @@
- `ignorePatterns`: a list of [glob](<https://en.wikipedia.org/wiki/Glob_(programming)>) patterns that Quartz should ignore and not search through when looking for files inside the `content` folder. See [[private pages]] for more details.
- `defaultDateType`: whether to use created, modified, or published as the default date to display on pages and page listings.
- `theme`: configure how the site looks.
- - `cdnCaching`: If `true` (default), use Google CDN to cache the fonts. This will generally will be faster. Disable (`false`) this if you want Quartz to download the fonts to be self-contained.
+ - `cdnCaching`: if `true` (default), use Google CDN to cache the fonts. This will generally be faster. Disable (`false`) this if you want Quartz to download the fonts to be self-contained.
- `typography`: what fonts to use. Any font available on [Google Fonts](https://fonts.google.com/) works here.
- - `header`: Font to use for headers
- - `code`: Font for inline and block quotes.
- - `body`: Font for everything
+ - `title`: font for the title of the site (optional, same as `header` by default)
+ - `header`: font to use for headers
+ - `code`: font for inline and block quotes
+ - `body`: font for everything
- `colors`: controls the theming of the site.
- `light`: page background
- `lightgray`: borders
diff --git a/quartz/components/Head.tsx b/quartz/components/Head.tsx
index 60dce6e..23183ca 100644
--- a/quartz/components/Head.tsx
+++ b/quartz/components/Head.tsx
@@ -1,7 +1,7 @@
import { i18n } from "../i18n"
import { FullSlug, getFileExtension, joinSegments, pathToRoot } from "../util/path"
import { CSSResourceToStyleElement, JSResourceToScriptElement } from "../util/resources"
-import { googleFontHref } from "../util/theme"
+import { googleFontHref, googleFontSubsetHref } from "../util/theme"
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
import { unescapeHTML } from "../util/escape"
import { CustomOgImagesEmitterName } from "../plugins/emitters/ogImage"
@@ -45,6 +45,9 @@
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link rel="stylesheet" href={googleFontHref(cfg.theme)} />
+ {cfg.theme.typography.title && (
+ <link rel="stylesheet" href={googleFontSubsetHref(cfg.theme, cfg.pageTitle)} />
+ )}
</>
)}
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossOrigin="anonymous" />
diff --git a/quartz/components/PageTitle.tsx b/quartz/components/PageTitle.tsx
index 046dc52..53ee824 100644
--- a/quartz/components/PageTitle.tsx
+++ b/quartz/components/PageTitle.tsx
@@ -17,6 +17,7 @@
.page-title {
font-size: 1.75rem;
margin: 0;
+ font-family: var(--titleFont);
}
`
diff --git a/quartz/plugins/emitters/componentResources.ts b/quartz/plugins/emitters/componentResources.ts
index 540a373..5dd67e6 100644
--- a/quartz/plugins/emitters/componentResources.ts
+++ b/quartz/plugins/emitters/componentResources.ts
@@ -9,7 +9,12 @@
import popoverStyle from "../../components/styles/popover.scss"
import { BuildCtx } from "../../util/ctx"
import { QuartzComponent } from "../../components/types"
-import { googleFontHref, joinStyles, processGoogleFonts } from "../../util/theme"
+import {
+ googleFontHref,
+ googleFontSubsetHref,
+ joinStyles,
+ processGoogleFonts,
+} from "../../util/theme"
import { Features, transform } from "lightningcss"
import { transform as transpile } from "esbuild"
import { write } from "./helpers"
@@ -211,9 +216,16 @@
// 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
- const response = await fetch(googleFontHref(ctx.cfg.configuration.theme))
+ const theme = ctx.cfg.configuration.theme
+ const response = await fetch(googleFontHref(theme))
googleFontsStyleSheet = await response.text()
+ if (theme.typography.title) {
+ const title = ctx.cfg.configuration.pageTitle
+ const response = await fetch(googleFontSubsetHref(theme, title))
+ googleFontsStyleSheet += `\n${await response.text()}`
+ }
+
if (!cfg.baseUrl) {
throw new Error(
"baseUrl must be defined when using Google Fonts without cfg.theme.cdnCaching",
diff --git a/quartz/util/theme.ts b/quartz/util/theme.ts
index 56261e3..4a06425 100644
--- a/quartz/util/theme.ts
+++ b/quartz/util/theme.ts
@@ -25,6 +25,7 @@
export interface Theme {
typography: {
+ title?: FontSpecification
header: FontSpecification
body: FontSpecification
code: FontSpecification
@@ -48,7 +49,10 @@
return spec.name
}
-function formatFontSpecification(type: "header" | "body" | "code", spec: FontSpecification) {
+function formatFontSpecification(
+ type: "title" | "header" | "body" | "code",
+ spec: FontSpecification,
+) {
if (typeof spec === "string") {
spec = { name: spec }
}
@@ -82,12 +86,19 @@
}
export function googleFontHref(theme: Theme) {
- const { code, header, body } = theme.typography
+ const { header, body, code } = theme.typography
const headerFont = formatFontSpecification("header", header)
const bodyFont = formatFontSpecification("body", body)
const codeFont = formatFontSpecification("code", code)
- return `https://fonts.googleapis.com/css2?family=${bodyFont}&family=${headerFont}&family=${codeFont}&display=swap`
+ return `https://fonts.googleapis.com/css2?family=${headerFont}&family=${bodyFont}&family=${codeFont}&display=swap`
+}
+
+export function googleFontSubsetHref(theme: Theme, text: string) {
+ const title = theme.typography.title || theme.typography.header
+ const titleFont = formatFontSpecification("title", title)
+
+ return `https://fonts.googleapis.com/css2?family=${titleFont}&text=${encodeURIComponent(text)}&display=swap`
}
export interface GoogleFontFile {
@@ -135,6 +146,7 @@
--highlight: ${theme.colors.lightMode.highlight};
--textHighlight: ${theme.colors.lightMode.textHighlight};
+ --titleFont: "${getFontSpecificationName(theme.typography.title || theme.typography.header)}", ${DEFAULT_SANS_SERIF};
--headerFont: "${getFontSpecificationName(theme.typography.header)}", ${DEFAULT_SANS_SERIF};
--bodyFont: "${getFontSpecificationName(theme.typography.body)}", ${DEFAULT_SANS_SERIF};
--codeFont: "${getFontSpecificationName(theme.typography.code)}", ${DEFAULT_MONO};
--
Gitblit v1.10.0