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`,
and `fonts/` (self-hosted Source
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
termotohtori.fi) is fragile — do not tweak.
- Vite builds ES-module `.js` outputs; the backend renders `<script
+1 -1
View File
@@ -169,7 +169,7 @@ evolves.
`/_assets/`
(Source Serif 4 for headings, Source Sans 3 for body, Fira Code for code
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
requests.
+15 -5
View File
@@ -395,6 +395,8 @@ function applyCustomCss(css) {
}
function onCustomCssInput() {
// Keep the font picker selection in sync with manual edits to the CSS.
parseFonts(customCss.value)
applyCustomCss(customCss.value)
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
// last font row goes away. Values reference the per-family variables from
// 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 = [
{ value: 'var(--font-source-serif)', label: 'Source Serif 4', serif: true },
{ value: 'var(--font-fraunces)', label: 'Fraunces', serif: true },
{ value: 'var(--font-literata)', label: 'Literata', serif: true },
{ value: 'var(--font-cormorant)', label: 'Cormorant', 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-inter)', label: 'Inter', serif: false },
{ value: 'var(--font-montserrat)', label: 'Montserrat', serif: false },
@@ -480,10 +485,15 @@ function fontRows() {
function onFontChange() {
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
.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')
.replace(/:root\s*\{\s*\}\n?/g, '')
if (rows.length) {
@@ -501,7 +511,7 @@ function onFontChange() {
function parseFonts(css) {
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')
fontHeading.value = get('heading')
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: '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: '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) 2009, Peter Wiegel.
Copyright (c) 2011, Pablo Impallari (www.impallari.com|impallari@gmail.com),
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 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-cause: "Cause", 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-heading: var(--font-source-serif);
/* The brand follows the heading font unless overridden separately. */