-
Notifications
You must be signed in to change notification settings - Fork 410
Description
Description
When using light/dark theme toggling, certain dark syntax highlighting themes (zenburn, espresso) don't generate a base .sourceCode > span text color rule. The light theme's near-black base color persists in dark mode, making code tokens without a specific highlighting class invisible.
Root Cause
The bug is in generateThemeCssClasses(), not in the theme files. The function only emits the .sourceCode > span base color rule when it finds a "Normal" key in "text-styles". It never checks the top-level "text-color" as a fallback.
kate (light theme) has "Normal" in "text-styles":
"text-styles": {
"Normal": {"text-color": "#1f1c1b", ...}
}→ Generates .sourceCode > span { color: #1f1c1b; }
zenburn (dark theme) is a valid Pandoc/KDE theme file — it defines "text-color": "#cccccc" at the top level, which is how these theme files can specify the default text color. But it has no "Normal" entry in "text-styles":
{
"text-color": "#cccccc",
"background-color": "#303030",
"text-styles": {
"Alert": {...},
"Keyword": {...},
...
// no "Normal" key
}
}→ No base .sourceCode > span rule is generated.
Since Quarto layers dark CSS on top of light (// note: dark is layered on light, we don't disable primary!), the light theme's .sourceCode > span { color: #1f1c1b; } persists unchallenged in dark mode.
Note: the triple-stylesheet issue from #13450 is unrelated — Puppeteer testing confirms the quarto-color-scheme-extra sheets are properly disabled by JS on page load and don't cause this problem.
Affected Themes
7 themes are missing "Normal" in text-styles: espresso, haddock, monochrome, none, pygments, tango, zenburn.
Of the dark themes, espresso and zenburn are both affected — they define a top-level text-color but no "Normal" style. Any user-created custom theme with the same valid structure would also break silently.
Reproduction
# _quarto.yml
format:
html:
theme:
light: cosmo
dark: darkly
highlight-style:
light: kate
dark: zenburnAny code block with tokens that don't get a specific span class (e.g., plain identifiers, punctuation) will be unreadable in dark mode:
Proposed Fix
In generateThemeCssClasses(), after processing text-styles, fall back to the theme's top-level "text-color" when no "Normal" style was found:
// After the Object.keys(textStyles).forEach loop:
if (!tokenCssByAbbr[""] && themeJson["text-color"]) {
const cssValues = [` color: ${themeJson["text-color"]};`, " font-style: inherit;"];
toCSS("", "Normal", cssValues);
["pre > code.sourceCode > span", "code.sourceCode > span",
"div.sourceCode,\ndiv.sourceCode pre.sourceCode"]
.forEach((selector) => {
otherLines.push(`\n${selector} {`);
otherLines.push(...cssValues);
otherLines.push("}\n");
});
}Verified by creating a patched zenburn theme with "Normal" added (simulating the fix output) — dark highlighting CSS then emits .sourceCode > span { color: #cccccc; } and all code tokens are readable without any custom SCSS workarounds.
Workaround
body.quarto-dark {
pre.sourceCode,
.sourceCode > span,
code.sourceCode > span {
color: #dcdccc;
}
}Environment
- Quarto 1.8.27
- macOS, Chrome/Safari