fix: default hoverTokenBackgroundColor to transparent

- Change default from rgba(54, 58, 79, 0.84) to transparent in config, CSS, and sanitizer fallbacks
- Update tests and docs to reflect new default
This commit is contained in:
2026-05-20 16:31:59 -07:00
parent e18b6eda77
commit fcd6511aa1
9 changed files with 20 additions and 25 deletions
+1 -1
View File
@@ -378,7 +378,7 @@
"text-shadow": "0 2px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.55)", // Text shadow setting.
"backdrop-filter": "blur(6px)", // Backdrop filter setting.
"--subtitle-hover-token-color": "#f4dbd6", // Subtitle hover token color setting.
"--subtitle-hover-token-background-color": "rgba(54, 58, 79, 0.84)" // Subtitle hover token background color setting.
"--subtitle-hover-token-background-color": "transparent" // Subtitle hover token background color setting.
}, // CSS declaration object applied to primary subtitles after normal subtitle style defaults.
"enableJlpt": false, // Enable JLPT vocabulary level underlines. When disabled, JLPT tagging lookup and underlines are skipped. Values: true | false
"preserveLineBreaks": false, // Preserve line breaks in visible overlay subtitle rendering. When false, line breaks are flattened to spaces for a single-line flow. Values: true | false
+1 -1
View File
@@ -390,7 +390,7 @@ See `config.example.jsonc` for detailed configuration options.
| `autoPauseVideoOnHover` | boolean | Pause playback while mouse hovers subtitle text, then resume on leave (`true` by default). |
| `autoPauseVideoOnYomitanPopup` | boolean | Pause playback while the Yomitan popup is open, then resume when the popup closes (`true` by default). |
| `hoverTokenColor` | string | Hex color used for hovered subtitle token highlight in mpv (default: catppuccin mauve) |
| `hoverTokenBackgroundColor` | string | CSS color used for hovered subtitle token background highlight; `hoverBackground` is accepted as an alias |
| `hoverTokenBackgroundColor` | string | CSS color used for hovered subtitle token background highlight (default: `"transparent"`); `hoverBackground` is accepted as an alias |
| `nameMatchEnabled` | boolean | Enable subtitle token coloring for matches from the SubMiner character dictionary (`true` by default) |
| `nameMatchColor` | string | Hex color used for subtitle tokens matched from the SubMiner character dictionary (default: `#f5bde6`) |
| `knownWordColor` | string | Hex color used for known-word subtitle highlights (default: `#a6da95`) |
+1 -1
View File
@@ -378,7 +378,7 @@
"text-shadow": "0 2px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.55)", // Text shadow setting.
"backdrop-filter": "blur(6px)", // Backdrop filter setting.
"--subtitle-hover-token-color": "#f4dbd6", // Subtitle hover token color setting.
"--subtitle-hover-token-background-color": "rgba(54, 58, 79, 0.84)" // Subtitle hover token background color setting.
"--subtitle-hover-token-background-color": "transparent" // Subtitle hover token background color setting.
}, // CSS declaration object applied to primary subtitles after normal subtitle style defaults.
"enableJlpt": false, // Enable JLPT vocabulary level underlines. When disabled, JLPT tagging lookup and underlines are skipped. Values: true | false
"preserveLineBreaks": false, // Preserve line breaks in visible overlay subtitle rendering. When false, line breaks are flattened to spaces for a single-line flow. Values: true | false
+1 -1
View File
@@ -102,7 +102,7 @@ test('loads defaults when config is missing', () => {
assert.equal(config.subtitleStyle.autoPauseVideoOnYomitanPopup, true);
assert.equal(config.subtitleSidebar.enabled, true);
assert.equal(config.subtitleStyle.hoverTokenColor, '#f4dbd6');
assert.equal(config.subtitleStyle.hoverTokenBackgroundColor, 'rgba(54, 58, 79, 0.84)');
assert.equal(config.subtitleStyle.hoverTokenBackgroundColor, 'transparent');
assert.equal(config.subtitleStyle.fontFamily, DEFAULT_SUBTITLE_FONT_FAMILY);
assert.equal(config.subtitleStyle.fontWeight, '600');
assert.equal(config.subtitleStyle.lineHeight, 1.35);
+1 -1
View File
@@ -9,7 +9,7 @@ export const SUBTITLE_DEFAULT_CONFIG: Pick<ResolvedConfig, 'subtitleStyle' | 'su
autoPauseVideoOnHover: true,
autoPauseVideoOnYomitanPopup: true,
hoverTokenColor: '#f4dbd6',
hoverTokenBackgroundColor: 'rgba(54, 58, 79, 0.84)',
hoverTokenBackgroundColor: 'transparent',
nameMatchEnabled: true,
nameMatchColor: '#f5bde6',
fontFamily: 'Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP',
+6 -6
View File
@@ -660,7 +660,7 @@ body.subtitle-sidebar-embedded-open #subtitleContainer {
--subtitle-jlpt-n4-color: #a6e3a1;
--subtitle-jlpt-n5-color: #8aadf4;
--subtitle-hover-token-color: #f4dbd6;
--subtitle-hover-token-background-color: rgba(54, 58, 79, 0.84);
--subtitle-hover-token-background-color: transparent;
--subtitle-frequency-single-color: #f5a97f;
--subtitle-frequency-band-1-color: #ed8796;
--subtitle-frequency-band-2-color: #f5a97f;
@@ -719,7 +719,7 @@ body.settings-modal-open [data-subminer-yomitan-popup-host='true'] {
}
#subtitleRoot .c:hover {
background: var(--subtitle-hover-token-background-color, rgba(54, 58, 79, 0.84));
background: var(--subtitle-hover-token-background-color, transparent);
color: var(--subtitle-hover-token-color, #f4dbd6) !important;
-webkit-text-fill-color: var(--subtitle-hover-token-color, #f4dbd6) !important;
border-radius: 2px;
@@ -884,7 +884,7 @@ body.settings-modal-open [data-subminer-yomitan-popup-host='true'] {
):not(.word-frequency-band-1):not(.word-frequency-band-2):not(.word-frequency-band-3):not(
.word-frequency-band-4
):not(.word-frequency-band-5):hover {
background: var(--subtitle-hover-token-background-color, rgba(54, 58, 79, 0.84));
background: var(--subtitle-hover-token-background-color, transparent);
border-radius: 3px;
color: var(--subtitle-hover-token-color, #f4dbd6) !important;
-webkit-text-fill-color: var(--subtitle-hover-token-color, #f4dbd6) !important;
@@ -899,7 +899,7 @@ body.settings-modal-open [data-subminer-yomitan-popup-host='true'] {
#subtitleRoot .word.word-frequency-band-3:hover,
#subtitleRoot .word.word-frequency-band-4:hover,
#subtitleRoot .word.word-frequency-band-5:hover {
background: var(--subtitle-hover-token-background-color, rgba(54, 58, 79, 0.84));
background: var(--subtitle-hover-token-background-color, transparent);
border-radius: 3px;
filter: brightness(1.18) saturate(1.08);
}
@@ -933,13 +933,13 @@ body.settings-modal-open [data-subminer-yomitan-popup-host='true'] {
#subtitleRoot::selection,
#subtitleRoot .word::selection,
#subtitleRoot .c::selection {
background: var(--subtitle-hover-token-background-color, rgba(54, 58, 79, 0.84));
background: var(--subtitle-hover-token-background-color, transparent);
color: var(--subtitle-hover-token-color, #f4dbd6) !important;
-webkit-text-fill-color: var(--subtitle-hover-token-color, #f4dbd6) !important;
}
#subtitleRoot *::selection {
background: var(--subtitle-hover-token-background-color, rgba(54, 58, 79, 0.84)) !important;
background: var(--subtitle-hover-token-background-color, transparent) !important;
color: var(--subtitle-hover-token-color, #f4dbd6) !important;
-webkit-text-fill-color: var(--subtitle-hover-token-color, #f4dbd6) !important;
}
+5 -8
View File
@@ -1066,10 +1066,7 @@ test('subtitle annotation CSS underlines JLPT tokens without changing token colo
const subtitleRootBlock = extractClassBlock(cssText, '#subtitleRoot');
assert.match(subtitleRootBlock, /--subtitle-hover-token-color:\s*#f4dbd6;/);
assert.match(
subtitleRootBlock,
/--subtitle-hover-token-background-color:\s*rgba\(54,\s*58,\s*79,\s*0\.84\);/,
);
assert.match(subtitleRootBlock, /--subtitle-hover-token-background-color:\s*transparent;/);
assert.match(subtitleRootBlock, /-webkit-text-fill-color:\s*currentColor;/);
const charBlock = extractClassBlock(cssText, '#subtitleRoot .c');
@@ -1123,7 +1120,7 @@ test('subtitle annotation CSS underlines JLPT tokens without changing token colo
);
assert.match(
plainWordHoverBlock,
/background:\s*var\(--subtitle-hover-token-background-color,\s*rgba\(54,\s*58,\s*79,\s*0\.84\)\);/,
/background:\s*var\(--subtitle-hover-token-background-color,\s*transparent\);/,
);
assert.match(
plainWordHoverBlock,
@@ -1137,7 +1134,7 @@ test('subtitle annotation CSS underlines JLPT tokens without changing token colo
const coloredWordHoverBlock = extractClassBlock(cssText, '#subtitleRoot .word.word-known:hover');
assert.match(
coloredWordHoverBlock,
/background:\s*var\(--subtitle-hover-token-background-color,\s*rgba\(54,\s*58,\s*79,\s*0\.84\)\);/,
/background:\s*var\(--subtitle-hover-token-background-color,\s*transparent\);/,
);
assert.match(coloredWordHoverBlock, /border-radius:\s*3px;/);
assert.match(coloredWordHoverBlock, /filter:\s*brightness\(1\.18\) saturate\(1\.08\);/);
@@ -1246,7 +1243,7 @@ test('subtitle annotation CSS underlines JLPT tokens without changing token colo
const selectionBlock = extractClassBlock(cssText, '#subtitleRoot::selection');
assert.match(
selectionBlock,
/background:\s*var\(--subtitle-hover-token-background-color,\s*rgba\(54,\s*58,\s*79,\s*0\.84\)\);/,
/background:\s*var\(--subtitle-hover-token-background-color,\s*transparent\);/,
);
assert.match(
selectionBlock,
@@ -1260,7 +1257,7 @@ test('subtitle annotation CSS underlines JLPT tokens without changing token colo
const descendantSelectionBlock = extractClassBlock(cssText, '#subtitleRoot *::selection');
assert.match(
descendantSelectionBlock,
/background:\s*var\(--subtitle-hover-token-background-color,\s*rgba\(54,\s*58,\s*79,\s*0\.84\)\)\s*!important;/,
/background:\s*var\(--subtitle-hover-token-background-color,\s*transparent\)\s*!important;/,
);
assert.match(
descendantSelectionBlock,
+2 -4
View File
@@ -80,12 +80,10 @@ export function sanitizeSubtitleHoverTokenColor(value: unknown): string {
function sanitizeSubtitleHoverTokenBackgroundColor(value: unknown): string {
if (typeof value !== 'string') {
return 'rgba(54, 58, 79, 0.84)';
return 'transparent';
}
const trimmed = value.trim();
return trimmed.length > 0 && SAFE_CSS_COLOR_PATTERN.test(trimmed)
? trimmed
: 'rgba(54, 58, 79, 0.84)';
return trimmed.length > 0 && SAFE_CSS_COLOR_PATTERN.test(trimmed) ? trimmed : 'transparent';
}
const DEFAULT_FREQUENCY_RENDER_SETTINGS: FrequencyRenderSettings = {
+2 -2
View File
@@ -14,7 +14,7 @@ test('serializeSubtitleCssDeclarations builds primary CSS from all managed appea
'subtitleStyle.fontColor': '#cad3f5',
'subtitleStyle.backgroundColor': 'transparent',
'subtitleStyle.hoverTokenColor': '#f4dbd6',
'subtitleStyle.hoverTokenBackgroundColor': 'rgba(54, 58, 79, 0.84)',
'subtitleStyle.hoverTokenBackgroundColor': 'transparent',
'subtitleStyle.paintOrder': 'stroke fill',
'subtitleStyle.WebkitTextStroke': '1.5px #000',
'subtitleStyle.textShadow': '0 2px 6px rgba(0,0,0,0.9)',
@@ -29,7 +29,7 @@ test('serializeSubtitleCssDeclarations builds primary CSS from all managed appea
assert.match(css, /color: #cad3f5;/);
assert.match(css, /background-color: transparent;/);
assert.match(css, /--subtitle-hover-token-color: #f4dbd6;/);
assert.match(css, /--subtitle-hover-token-background-color: rgba\(54, 58, 79, 0.84\);/);
assert.match(css, /--subtitle-hover-token-background-color: transparent;/);
assert.match(css, /paint-order: stroke fill;/);
assert.match(css, /-webkit-text-stroke: 1.5px #000;/);
assert.doesNotMatch(css, /--subtitle-known-word-color:/);