fix(reader): keep table background matching the page in dark mode (#4419) (#4426)

The dark-mode `table *` color-mix tint in getColorStyles was applied
unconditionally since #4055, so plain tables — and the invisible spacer
cells some books use for vertical TOC layout — rendered a few shades off
the page background, and the spacing between words appeared to change.

Restore the `overrideColor` gate that #2377 originally added. Illegible
light/zebra table backgrounds (the #4028 case #4055 targeted) are now
handled separately by the dark-mode light-background rewriters from
#4392, so the blanket tint is no longer needed by default. The
standalone blockquote tint stays unconditional in dark mode.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-06-03 00:20:59 +08:00
committed by GitHub
parent 7128e8964e
commit 9d8062ae27
2 changed files with 36 additions and 2 deletions
@@ -639,6 +639,33 @@ describe('getColorStyles branches (via getStyles)', () => {
);
});
it('does not tint table descendants in dark mode when overrideColor is false (#4419)', () => {
const vs = makeViewSettings({ overrideColor: false });
const theme = makeThemeCode({ isDarkMode: true, bg: '#1a1a1a', fg: '#e0e0e0' });
const css = getStyles(vs, theme);
// When the user has NOT enabled color override, the `blockquote, table *`
// rule must not paint a tinted background on table descendants. Otherwise
// plain tables — and the invisible spacer cells some books use for vertical
// layout — render with a color different from the page background, and the
// spacing between words appears to change in dark mode. Regression from
// #4055; the #4028 zebra-row legibility case is now handled by the
// light-background rewriters from #4392. See issue #4419.
const match = css.match(/blockquote,\s*table\s*\*\s*\{([^}]*)\}/);
expect(match).not.toBeNull();
expect(match![1]).not.toContain('color-mix');
});
it('still tints blockquotes in dark mode when overrideColor is false', () => {
const vs = makeViewSettings({ overrideColor: false });
const theme = makeThemeCode({ isDarkMode: true, bg: '#1a1a1a', fg: '#e0e0e0' });
const css = getStyles(vs, theme);
// The standalone `blockquote` rule keeps its dark-mode tint regardless of
// overrideColor — only the shared `table *` part is gated.
expect(css).toMatch(
/blockquote\s*\{[^}]*background:\s*color-mix\(in srgb,\s*#1a1a1a\s*80%,\s*#000\)/,
);
});
it('makes svg/img backgrounds transparent when overrideColor is true', () => {
const vs = makeViewSettings({ overrideColor: true });
const theme = makeThemeCode();
+9 -2
View File
@@ -258,9 +258,16 @@ const getColorStyles = (
blockquote {
${isDarkMode ? `background: color-mix(in srgb, ${bg} 80%, #000);` : ''}
}
/* Only tint table descendants when the user has opted into color override.
By default, leave them transparent so a plain table (and the invisible
spacer cells some books use for vertical layout) keeps the page
background instead of a different shade. Illegible light/zebra table
backgrounds are handled separately by the dark-mode light-background
rewriters (getDarkModeLightBackgroundOverrides / transformStylesheet).
See #4419 (and #2377, which this gate originally fixed). */
blockquote, table * {
${isDarkMode ? `background: color-mix(in srgb, ${bg} 80%, #000);` : ''}
${isDarkMode ? `background-color: color-mix(in srgb, ${bg} 80%, #000);` : ''}
${isDarkMode && overrideColor ? `background: color-mix(in srgb, ${bg} 80%, #000);` : ''}
${isDarkMode && overrideColor ? `background-color: color-mix(in srgb, ${bg} 80%, #000);` : ''}
}
/* override inline hardcoded text color */
font[color="#000000"], font[color="#000"], font[color="black"],