Replace UnifrakturMaguntia with New Rocker, fix font picker duplicates

Picker font-variable regexes only allowed [a-z-], so --font-exo2 was
never parsed or stripped: picking another font left the old row behind
and the selection showed wrong. Now digits are allowed, stripping is
declaration-level (handles inline rows) and removes all font rows
before inserting, and the picker re-parses on every CSS edit so manual
changes update the selection live.
This commit is contained in:
2026-08-17 19:50:40 +00:00
parent 6a68a7832a
commit 40617f8080
8 changed files with 23 additions and 11 deletions
+1 -1
View File
@@ -117,7 +117,7 @@ not for the public pages. See `docs/design-principles.md` for the design.
an orange racing-tab nav clipped with a bezier `shape()`), `pygments.css`, an orange racing-tab nav clipped with a bezier `shape()`), `pygments.css`,
and `fonts/` (self-hosted Source and `fonts/` (self-hosted Source
Sans 3/Source Serif 4/Fraunces/Literata/Cormorant/Playfair Sans 3/Source Serif 4/Fraunces/Literata/Cormorant/Playfair
Display/Inter/Montserrat/Fira Code/Cause/Exo 2/UnifrakturMaguntia Display/Inter/Montserrat/Fira Code/Cause/Exo 2/New Rocker
variable woff2). The `::view-transition*` block at the end of `pagerite.css` (from variable woff2). The `::view-transition*` block at the end of `pagerite.css` (from
termotohtori.fi) is fragile — do not tweak. termotohtori.fi) is fragile — do not tweak.
- Vite builds ES-module `.js` outputs; the backend renders `<script - Vite builds ES-module `.js` outputs; the backend renders `<script
+1 -1
View File
@@ -169,7 +169,7 @@ evolves.
`/_assets/` `/_assets/`
(Source Serif 4 for headings, Source Sans 3 for body, Fira Code for code (Source Serif 4 for headings, Source Sans 3 for body, Fira Code for code
by default; Fraunces, Literata, Cormorant, Playfair Display, Inter, by default; Fraunces, Literata, Cormorant, Playfair Display, Inter,
Montserrat, Cause, Exo 2 and UnifrakturMaguntia kept as woff2 options with Montserrat, Cause, Exo 2 and New Rocker kept as woff2 options with
local `@font-face`, variable-weight where available). No third-party local `@font-face`, variable-weight where available). No third-party
requests. requests.
+15 -5
View File
@@ -395,6 +395,8 @@ function applyCustomCss(css) {
} }
function onCustomCssInput() { function onCustomCssInput() {
// Keep the font picker selection in sync with manual edits to the CSS.
parseFonts(customCss.value)
applyCustomCss(customCss.value) applyCustomCss(customCss.value)
debounce('custom-css', saveCustomCss, 400) debounce('custom-css', saveCustomCss, 400)
} }
@@ -417,14 +419,17 @@ function setCssDocument(text) {
// and rewritten — adding a :root block if none exists, dropping it when the // and rewritten — adding a :root block if none exists, dropping it when the
// last font row goes away. Values reference the per-family variables from // last font row goes away. Values reference the per-family variables from
// pagerite.css, so no font stacks are spelled out here. // pagerite.css, so no font stacks are spelled out here.
const FONT_ROW = /^\s*--font-(body|heading|brand):\s*var\(--font-[a-z-]+\);\s*$/ // Declaration-level match (not line-anchored): user-edited rows may sit
// inline with other content, and those must be stripped/parsed too or
// re-picking a font would insert a duplicate row.
const FONT_DECL = /--font-(?:body|heading|brand)\s*:\s*var\(--font-[a-z0-9-]+\)\s*;/g
const FONT_OPTIONS = [ const FONT_OPTIONS = [
{ value: 'var(--font-source-serif)', label: 'Source Serif 4', serif: true }, { value: 'var(--font-source-serif)', label: 'Source Serif 4', serif: true },
{ value: 'var(--font-fraunces)', label: 'Fraunces', serif: true }, { value: 'var(--font-fraunces)', label: 'Fraunces', serif: true },
{ value: 'var(--font-literata)', label: 'Literata', serif: true }, { value: 'var(--font-literata)', label: 'Literata', serif: true },
{ value: 'var(--font-cormorant)', label: 'Cormorant', serif: true }, { value: 'var(--font-cormorant)', label: 'Cormorant', serif: true },
{ value: 'var(--font-playfair)', label: 'Playfair Display', serif: true }, { value: 'var(--font-playfair)', label: 'Playfair Display', serif: true },
{ value: 'var(--font-unifraktur)', label: 'UnifrakturMaguntia', serif: true }, { value: 'var(--font-new-rocker)', label: 'New Rocker', serif: true },
{ value: 'var(--font-source-sans)', label: 'Source Sans 3', serif: false }, { value: 'var(--font-source-sans)', label: 'Source Sans 3', serif: false },
{ value: 'var(--font-inter)', label: 'Inter', serif: false }, { value: 'var(--font-inter)', label: 'Inter', serif: false },
{ value: 'var(--font-montserrat)', label: 'Montserrat', serif: false }, { value: 'var(--font-montserrat)', label: 'Montserrat', serif: false },
@@ -480,10 +485,15 @@ function fontRows() {
function onFontChange() { function onFontChange() {
const rows = fontRows() const rows = fontRows()
// Strip our rows wherever they are, then drop :root blocks left empty. // Strip our declarations wherever they are (even inline with other
// content), drop lines they emptied, then drop :root blocks left empty.
let css = customCss.value let css = customCss.value
.split('\n') .split('\n')
.filter((l) => !FONT_ROW.test(l)) .map((l) => {
const stripped = l.replace(FONT_DECL, '')
return stripped === l ? l : stripped.trim() ? stripped : null
})
.filter((l) => l !== null)
.join('\n') .join('\n')
.replace(/:root\s*\{\s*\}\n?/g, '') .replace(/:root\s*\{\s*\}\n?/g, '')
if (rows.length) { if (rows.length) {
@@ -501,7 +511,7 @@ function onFontChange() {
function parseFonts(css) { function parseFonts(css) {
const get = (name) => const get = (name) =>
css.match(new RegExp(`^\\s*--font-${name}:\\s*(var\\(--font-[a-z-]+\\));`, 'm'))?.[1] || '' css.match(new RegExp(`--font-${name}\\s*:\\s*(var\\(--font-[a-z0-9-]+\\))\\s*;`))?.[1] || ''
fontBody.value = get('body') fontBody.value = get('body')
fontHeading.value = get('heading') fontHeading.value = get('heading')
fontBrand.value = get('brand') fontBrand.value = get('brand')
+1 -1
View File
@@ -17,4 +17,4 @@
@font-face { font-family: 'Cause'; font-weight: 100 900; font-style: normal; font-display: swap; src: url('cause.woff2') format('woff2'); } @font-face { font-family: 'Cause'; font-weight: 100 900; font-style: normal; font-display: swap; src: url('cause.woff2') format('woff2'); }
@font-face { font-family: 'Exo 2'; font-weight: 100 900; font-style: normal; font-display: swap; src: url('exo2.woff2') format('woff2'); } @font-face { font-family: 'Exo 2'; font-weight: 100 900; font-style: normal; font-display: swap; src: url('exo2.woff2') format('woff2'); }
@font-face { font-family: 'Exo 2'; font-weight: 100 900; font-style: italic; font-display: swap; src: url('exo2-italic.woff2') format('woff2'); } @font-face { font-family: 'Exo 2'; font-weight: 100 900; font-style: italic; font-display: swap; src: url('exo2-italic.woff2') format('woff2'); }
@font-face { font-family: 'UnifrakturMaguntia'; font-weight: 400; font-style: normal; font-display: swap; src: url('unifrakturmaguntia.woff2') format('woff2'); } @font-face { font-family: 'New Rocker'; font-weight: 400; font-style: normal; font-display: swap; src: url('newrocker.woff2') format('woff2'); }
@@ -1,5 +1,7 @@
Copyright (c) 2010, j. 'mach' wust, with Reserved Font Name UnifrakturMaguntia. Copyright (c) 2011, Pablo Impallari (www.impallari.com|impallari@gmail.com),
Copyright (c) 2009, Peter Wiegel. Copyright (c) 2011, Brenda Gallo (gbrenda1987@gmail.com),
Copyright (c) 2011, Rodrigo Fuenzalida (www.rfuenzalida.com|hello@rfuenzalida.com),
with Reserved Font Name 'New Rocker'
This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at: This license is copied below, and is also available with a FAQ at:
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -50,7 +50,7 @@
--font-fira-code: "Fira Code", ui-monospace, monospace; --font-fira-code: "Fira Code", ui-monospace, monospace;
--font-cause: "Cause", system-ui, sans-serif; --font-cause: "Cause", system-ui, sans-serif;
--font-exo2: "Exo 2", system-ui, sans-serif; --font-exo2: "Exo 2", system-ui, sans-serif;
--font-unifraktur: "UnifrakturMaguntia", "Playfair Display", serif; --font-new-rocker: "New Rocker", "Playfair Display", serif;
--font-body: var(--font-source-sans); --font-body: var(--font-source-sans);
--font-heading: var(--font-source-serif); --font-heading: var(--font-source-serif);
/* The brand follows the heading font unless overridden separately. */ /* The brand follows the heading font unless overridden separately. */