feat(config): refresh subtitle style defaults and drop plugin legacy startup alias

This commit is contained in:
2026-02-27 00:03:07 -08:00
parent bc6f581ea5
commit 3e9db1f125
9 changed files with 114 additions and 49 deletions

View File

@@ -13,11 +13,11 @@
"auto_start_overlay": false, // When overlay connects to mpv, automatically show overlay and hide mpv subtitles. Values: true | false "auto_start_overlay": false, // When overlay connects to mpv, automatically show overlay and hide mpv subtitles. Values: true | false
// ========================================== // ==========================================
// Visible Overlay Subtitle Binding (Legacy) // Visible Overlay Subtitle Binding
// Backward-compatible key. Runtime ignores this value. // Control whether visible overlay toggles also toggle MPV subtitle visibility.
// MPV subtitles are automatically hidden whenever any overlay subtitle mode is visible. // When enabled, visible overlay hides MPV subtitles; when disabled, MPV subtitles are left unchanged.
// ========================================== // ==========================================
"bind_visible_overlay_to_mpv_sub_visibility": true, // Legacy compatibility key (runtime no-op). Values: true | false "bind_visible_overlay_to_mpv_sub_visibility": true, // Link visible overlay toggles to MPV primary subtitle visibility. Values: true | false
// ========================================== // ==========================================
// Texthooker Server // Texthooker Server
@@ -112,17 +112,23 @@
// Hot-reload: subtitle style changes apply live without restarting SubMiner. // Hot-reload: subtitle style changes apply live without restarting SubMiner.
// ========================================== // ==========================================
"subtitleStyle": { "subtitleStyle": {
// Additional CSS declarations are also allowed and applied directly to subtitle roots/containers (for example: lineHeight, textShadow, -webkit-text-stroke, backdropFilter).
"enableJlpt": false, // Enable JLPT vocabulary level underlines. When disabled, JLPT tagging lookup and underlines are skipped. Values: true | false "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 "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
"hoverTokenColor": "#f4dbd6", // Hex color used for hovered subtitle token highlight in the overlay. "hoverTokenColor": "#f4dbd6", // Hex color used for hovered subtitle token highlight in mpv.
"hoverTokenBackgroundColor": "#363a4fd6", // CSS color used for hovered subtitle token background highlight in the overlay. "hoverTokenBackgroundColor": "rgba(54, 58, 79, 0.84)", // CSS color used for hovered subtitle token background highlight in mpv.
"fontFamily": "M PLUS 1, Noto Sans CJK JP Regular, Noto Sans CJK JP, Hiragino Sans, Hiragino Kaku Gothic ProN, Yu Gothic, Arial Unicode MS, Arial, sans-serif", // Font family setting. "fontFamily": "M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP", // Font family setting.
"fontSize": 35, // Font size setting. "fontSize": 35, // Font size setting.
"fontColor": "#cad3f5", // Font color setting. "fontColor": "#cad3f5", // Font color setting.
"fontWeight": "normal", // Font weight setting. "fontWeight": "600", // Font weight setting.
"lineHeight": 1.35, // Line height setting.
"letterSpacing": "-0.01em", // Letter spacing setting.
"wordSpacing": 0, // Word spacing setting.
"fontKerning": "normal", // Font kerning setting.
"textRendering": "geometricPrecision", // Text rendering setting.
"textShadow": "0 3px 10px rgba(0,0,0,0.69)", // Text shadow setting.
"fontStyle": "normal", // Font style setting. "fontStyle": "normal", // Font style setting.
"backgroundColor": "rgb(30, 32, 48, 0.88)", // Background color setting. "backgroundColor": "rgb(30, 32, 48, 0.88)", // Background color setting.
"backdropFilter": "blur(6px)", // Backdrop filter setting.
"nPlusOneColor": "#c6a0f6", // N plus one color setting. "nPlusOneColor": "#c6a0f6", // N plus one color setting.
"knownWordColor": "#a6da95", // Known word color setting. "knownWordColor": "#a6da95", // Known word color setting.
"jlptColors": { "jlptColors": {
@@ -147,12 +153,19 @@
] // Five colors used for rank bands when mode is `banded` (from most common to least within topX). ] // Five colors used for rank bands when mode is `banded` (from most common to least within topX).
}, // Frequency dictionary setting. }, // Frequency dictionary setting.
"secondary": { "secondary": {
"fontFamily": "Manrope, Inter", // Font family setting.
"fontSize": 24, // Font size setting. "fontSize": 24, // Font size setting.
"fontColor": "#ffffff", // Font color setting. "fontColor": "#cad3f5", // Font color setting.
"lineHeight": 1.35, // Line height setting.
"letterSpacing": "-0.01em", // Letter spacing setting.
"wordSpacing": 0, // Word spacing setting.
"fontKerning": "normal", // Font kerning setting.
"textRendering": "geometricPrecision", // Text rendering setting.
"textShadow": "0 3px 10px rgba(0,0,0,0.69)", // Text shadow setting.
"backgroundColor": "transparent", // Background color setting. "backgroundColor": "transparent", // Background color setting.
"backdropFilter": "blur(6px)", // Backdrop filter setting.
"fontWeight": "normal", // Font weight setting. "fontWeight": "normal", // Font weight setting.
"fontStyle": "normal", // Font style setting. "fontStyle": "normal" // Font style setting.
"fontFamily": "M PLUS 1, Noto Sans CJK JP Regular, Noto Sans CJK JP, Hiragino Sans, Hiragino Kaku Gothic ProN, Yu Gothic, Arial Unicode MS, Arial, sans-serif" // Font family setting.
} // Secondary setting. } // Secondary setting.
}, // Primary and secondary subtitle styling. }, // Primary and secondary subtitle styling.

View File

@@ -724,15 +724,23 @@ See `config.example.jsonc` for detailed configuration options.
```json ```json
{ {
"subtitleStyle": { "subtitleStyle": {
"fontFamily": "Noto Sans CJK JP Regular, Noto Sans CJK JP, Arial Unicode MS, Arial, sans-serif", "fontFamily": "M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP",
"fontSize": 35, "fontSize": 35,
"fontColor": "#cad3f5", "fontColor": "#cad3f5",
"fontWeight": "normal", "fontWeight": "600",
"lineHeight": 1.35,
"letterSpacing": "-0.01em",
"wordSpacing": 0,
"fontKerning": "normal",
"textRendering": "geometricPrecision",
"textShadow": "0 3px 10px rgba(0,0,0,0.69)",
"fontStyle": "normal", "fontStyle": "normal",
"backgroundColor": "rgb(30, 32, 48, 0.88)", "backgroundColor": "rgb(30, 32, 48, 0.88)",
"backdropFilter": "blur(6px)",
"secondary": { "secondary": {
"fontFamily": "Manrope, Inter",
"fontSize": 24, "fontSize": 24,
"fontColor": "#ffffff", "fontColor": "#cad3f5",
"backgroundColor": "transparent" "backgroundColor": "transparent"
} }
} }
@@ -741,10 +749,10 @@ See `config.example.jsonc` for detailed configuration options.
| Option | Values | Description | | Option | Values | Description |
| ---------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------- | | ---------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------- |
| `fontFamily` | string | CSS font-family value (default: `"Noto Sans CJK JP Regular, ..."`) | | `fontFamily` | string | CSS font-family value (default: `"M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP"`) |
| `fontSize` | number (px) | Font size in pixels (default: `35`) | | `fontSize` | number (px) | Font size in pixels (default: `35`) |
| `fontColor` | string | Any CSS color value (default: `"#cad3f5"`) | | `fontColor` | string | Any CSS color value (default: `"#cad3f5"`) |
| `fontWeight` | string | CSS font-weight, e.g. `"bold"`, `"normal"`, `"600"` (default: `"normal"`) | | `fontWeight` | string | CSS font-weight, e.g. `"bold"`, `"normal"`, `"600"` (default: `"600"`) |
| `fontStyle` | string | `"normal"` or `"italic"` (default: `"normal"`) | | `fontStyle` | string | `"normal"` or `"italic"` (default: `"normal"`) |
| `backgroundColor` | string | Any CSS color, including `"transparent"` (default: `"rgb(30, 32, 48, 0.88)"`) | | `backgroundColor` | string | Any CSS color, including `"transparent"` (default: `"rgb(30, 32, 48, 0.88)"`) |
| `enableJlpt` | boolean | Enable JLPT level underline styling (`false` by default) | | `enableJlpt` | boolean | Enable JLPT level underline styling (`false` by default) |
@@ -772,7 +780,7 @@ Lookup behavior:
In `single` mode all highlights use `singleColor`; in `banded` mode tokens map to five ascending color bands from most common to least common inside the topX window. In `single` mode all highlights use `singleColor`; in `banded` mode tokens map to five ascending color bands from most common to least common inside the topX window.
Secondary subtitle defaults: `fontSize: 24`, `fontColor: "#ffffff"`, `backgroundColor: "transparent"`. Any property not set in `secondary` falls back to the CSS defaults. Secondary subtitle defaults: `fontFamily: "Manrope, Inter"`, `fontSize: 24`, `fontColor: "#cad3f5"`, `backgroundColor: "transparent"`. Any property not set in `secondary` falls back to the CSS defaults.
**See `config.example.jsonc`** for the complete list of subtitle style configuration options. **See `config.example.jsonc`** for the complete list of subtitle style configuration options.

View File

@@ -17,7 +17,7 @@
// Control whether visible overlay toggles also toggle MPV subtitle visibility. // Control whether visible overlay toggles also toggle MPV subtitle visibility.
// When enabled, visible overlay hides MPV subtitles; when disabled, MPV subtitles are left unchanged. // When enabled, visible overlay hides MPV subtitles; when disabled, MPV subtitles are left unchanged.
// ========================================== // ==========================================
"bind_visible_overlay_to_mpv_sub_visibility": true, // Link visible overlay toggles to MPV subtitle visibility (primary and secondary). Values: true | false "bind_visible_overlay_to_mpv_sub_visibility": true, // Link visible overlay toggles to MPV primary subtitle visibility. Values: true | false
// ========================================== // ==========================================
// Texthooker Server // Texthooker Server
@@ -112,17 +112,23 @@
// Hot-reload: subtitle style changes apply live without restarting SubMiner. // Hot-reload: subtitle style changes apply live without restarting SubMiner.
// ========================================== // ==========================================
"subtitleStyle": { "subtitleStyle": {
// Additional CSS declarations are also allowed and applied directly to subtitle roots/containers (for example: lineHeight, textShadow, -webkit-text-stroke, backdropFilter).
"enableJlpt": false, // Enable JLPT vocabulary level underlines. When disabled, JLPT tagging lookup and underlines are skipped. Values: true | false "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 "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
"hoverTokenColor": "#f4dbd6", // Hex color used for hovered subtitle token highlight in the overlay. "hoverTokenColor": "#f4dbd6", // Hex color used for hovered subtitle token highlight in mpv.
"hoverTokenBackgroundColor": "#363a4fd6", // CSS color used for hovered subtitle token background highlight in the overlay. "hoverTokenBackgroundColor": "rgba(54, 58, 79, 0.84)", // CSS color used for hovered subtitle token background highlight in mpv.
"fontFamily": "M PLUS 1, Noto Sans CJK JP Regular, Noto Sans CJK JP, Hiragino Sans, Hiragino Kaku Gothic ProN, Yu Gothic, Arial Unicode MS, Arial, sans-serif", // Font family setting. "fontFamily": "M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP", // Font family setting.
"fontSize": 35, // Font size setting. "fontSize": 35, // Font size setting.
"fontColor": "#cad3f5", // Font color setting. "fontColor": "#cad3f5", // Font color setting.
"fontWeight": "normal", // Font weight setting. "fontWeight": "600", // Font weight setting.
"lineHeight": 1.35, // Line height setting.
"letterSpacing": "-0.01em", // Letter spacing setting.
"wordSpacing": 0, // Word spacing setting.
"fontKerning": "normal", // Font kerning setting.
"textRendering": "geometricPrecision", // Text rendering setting.
"textShadow": "0 3px 10px rgba(0,0,0,0.69)", // Text shadow setting.
"fontStyle": "normal", // Font style setting. "fontStyle": "normal", // Font style setting.
"backgroundColor": "rgb(30, 32, 48, 0.88)", // Background color setting. "backgroundColor": "rgb(30, 32, 48, 0.88)", // Background color setting.
"backdropFilter": "blur(6px)", // Backdrop filter setting.
"nPlusOneColor": "#c6a0f6", // N plus one color setting. "nPlusOneColor": "#c6a0f6", // N plus one color setting.
"knownWordColor": "#a6da95", // Known word color setting. "knownWordColor": "#a6da95", // Known word color setting.
"jlptColors": { "jlptColors": {
@@ -147,12 +153,19 @@
] // Five colors used for rank bands when mode is `banded` (from most common to least within topX). ] // Five colors used for rank bands when mode is `banded` (from most common to least within topX).
}, // Frequency dictionary setting. }, // Frequency dictionary setting.
"secondary": { "secondary": {
"fontFamily": "Manrope, Inter", // Font family setting.
"fontSize": 24, // Font size setting. "fontSize": 24, // Font size setting.
"fontColor": "#ffffff", // Font color setting. "fontColor": "#cad3f5", // Font color setting.
"lineHeight": 1.35, // Line height setting.
"letterSpacing": "-0.01em", // Letter spacing setting.
"wordSpacing": 0, // Word spacing setting.
"fontKerning": "normal", // Font kerning setting.
"textRendering": "geometricPrecision", // Text rendering setting.
"textShadow": "0 3px 10px rgba(0,0,0,0.69)", // Text shadow setting.
"backgroundColor": "transparent", // Background color setting. "backgroundColor": "transparent", // Background color setting.
"backdropFilter": "blur(6px)", // Backdrop filter setting.
"fontWeight": "normal", // Font weight setting. "fontWeight": "normal", // Font weight setting.
"fontStyle": "normal", // Font style setting. "fontStyle": "normal" // Font style setting.
"fontFamily": "M PLUS 1, Noto Sans CJK JP Regular, Noto Sans CJK JP, Hiragino Sans, Hiragino Kaku Gothic ProN, Yu Gothic, Arial Unicode MS, Arial, sans-serif" // Font family setting.
} // Secondary setting. } // Secondary setting.
}, // Primary and secondary subtitle styling. }, // Primary and secondary subtitle styling.

View File

@@ -26,9 +26,6 @@ auto_start=no
# Automatically show visible overlay when overlay starts # Automatically show visible overlay when overlay starts
auto_start_visible_overlay=no auto_start_visible_overlay=no
# Legacy alias (maps to auto_start_visible_overlay)
# auto_start_overlay=no
# Show OSD messages for overlay status # Show OSD messages for overlay status
osd_messages=yes osd_messages=yes

View File

@@ -134,7 +134,6 @@ local opts = {
texthooker_port = 5174, texthooker_port = 5174,
backend = "auto", backend = "auto",
auto_start = true, auto_start = true,
auto_start_overlay = false, -- legacy alias, maps to auto_start_visible_overlay
auto_start_visible_overlay = false, auto_start_visible_overlay = false,
osd_messages = true, osd_messages = true,
log_level = "info", log_level = "info",
@@ -1438,12 +1437,7 @@ local function parse_start_script_message_overrides(...)
end end
local function resolve_visible_overlay_startup() local function resolve_visible_overlay_startup()
local visible = coerce_bool(opts.auto_start_visible_overlay, false) return coerce_bool(opts.auto_start_visible_overlay, false)
-- Backward compatibility for old config key.
if coerce_bool(opts.auto_start_overlay, false) then
visible = true
end
return visible
end end
local function apply_startup_overlay_preferences() local function apply_startup_overlay_preferences()

View File

@@ -28,7 +28,21 @@ test('loads defaults when config is missing', () => {
assert.equal(config.subtitleStyle.backgroundColor, 'rgb(30, 32, 48, 0.88)'); assert.equal(config.subtitleStyle.backgroundColor, 'rgb(30, 32, 48, 0.88)');
assert.equal(config.subtitleStyle.preserveLineBreaks, false); assert.equal(config.subtitleStyle.preserveLineBreaks, false);
assert.equal(config.subtitleStyle.hoverTokenColor, '#f4dbd6'); assert.equal(config.subtitleStyle.hoverTokenColor, '#f4dbd6');
assert.equal(config.subtitleStyle.hoverTokenBackgroundColor, '#363a4fd6'); assert.equal(config.subtitleStyle.hoverTokenBackgroundColor, 'rgba(54, 58, 79, 0.84)');
assert.equal(
config.subtitleStyle.fontFamily,
'M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP',
);
assert.equal(config.subtitleStyle.fontWeight, '600');
assert.equal(config.subtitleStyle.lineHeight, 1.35);
assert.equal(config.subtitleStyle.letterSpacing, '-0.01em');
assert.equal(config.subtitleStyle.wordSpacing, 0);
assert.equal(config.subtitleStyle.fontKerning, 'normal');
assert.equal(config.subtitleStyle.textRendering, 'geometricPrecision');
assert.equal(config.subtitleStyle.textShadow, '0 3px 10px rgba(0,0,0,0.69)');
assert.equal(config.subtitleStyle.backdropFilter, 'blur(6px)');
assert.equal(config.subtitleStyle.secondary.fontFamily, 'Manrope, Inter');
assert.equal(config.subtitleStyle.secondary.fontColor, '#cad3f5');
assert.equal(config.immersionTracking.enabled, true); assert.equal(config.immersionTracking.enabled, true);
assert.equal(config.immersionTracking.dbPath, ''); assert.equal(config.immersionTracking.dbPath, '');
assert.equal(config.immersionTracking.batchSize, 25); assert.equal(config.immersionTracking.batchSize, 25);

View File

@@ -5,14 +5,20 @@ export const SUBTITLE_DEFAULT_CONFIG: Pick<ResolvedConfig, 'subtitleStyle'> = {
enableJlpt: false, enableJlpt: false,
preserveLineBreaks: false, preserveLineBreaks: false,
hoverTokenColor: '#f4dbd6', hoverTokenColor: '#f4dbd6',
hoverTokenBackgroundColor: '#363a4fd6', hoverTokenBackgroundColor: 'rgba(54, 58, 79, 0.84)',
fontFamily: fontFamily: 'M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP',
'M PLUS 1, Noto Sans CJK JP Regular, Noto Sans CJK JP, Hiragino Sans, Hiragino Kaku Gothic ProN, Yu Gothic, Arial Unicode MS, Arial, sans-serif',
fontSize: 35, fontSize: 35,
fontColor: '#cad3f5', fontColor: '#cad3f5',
fontWeight: 'normal', fontWeight: '600',
lineHeight: 1.35,
letterSpacing: '-0.01em',
wordSpacing: 0,
fontKerning: 'normal',
textRendering: 'geometricPrecision',
textShadow: '0 3px 10px rgba(0,0,0,0.69)',
fontStyle: 'normal', fontStyle: 'normal',
backgroundColor: 'rgb(30, 32, 48, 0.88)', backgroundColor: 'rgb(30, 32, 48, 0.88)',
backdropFilter: 'blur(6px)',
nPlusOneColor: '#c6a0f6', nPlusOneColor: '#c6a0f6',
knownWordColor: '#a6da95', knownWordColor: '#a6da95',
jlptColors: { jlptColors: {
@@ -31,13 +37,19 @@ export const SUBTITLE_DEFAULT_CONFIG: Pick<ResolvedConfig, 'subtitleStyle'> = {
bandedColors: ['#ed8796', '#f5a97f', '#f9e2af', '#a6e3a1', '#8aadf4'], bandedColors: ['#ed8796', '#f5a97f', '#f9e2af', '#a6e3a1', '#8aadf4'],
}, },
secondary: { secondary: {
fontFamily: 'Manrope, Inter',
fontSize: 24, fontSize: 24,
fontColor: '#ffffff', fontColor: '#cad3f5',
lineHeight: 1.35,
letterSpacing: '-0.01em',
wordSpacing: 0,
fontKerning: 'normal',
textRendering: 'geometricPrecision',
textShadow: '0 3px 10px rgba(0,0,0,0.69)',
backgroundColor: 'transparent', backgroundColor: 'transparent',
backdropFilter: 'blur(6px)',
fontWeight: 'normal', fontWeight: 'normal',
fontStyle: 'normal', fontStyle: 'normal',
fontFamily:
'M PLUS 1, Noto Sans CJK JP Regular, Noto Sans CJK JP, Hiragino Sans, Hiragino Kaku Gothic ProN, Yu Gothic, Arial Unicode MS, Arial, sans-serif',
}, },
}, },
}; };

View File

@@ -509,7 +509,7 @@ function renderSubtitle(data: SubtitleData | string): void {
if (style.fontColor) { if (style.fontColor) {
ctx.dom.subtitleRoot.style.color = style.fontColor; ctx.dom.subtitleRoot.style.color = style.fontColor;
} }
if (style.fontWeight) ctx.dom.subtitleRoot.style.fontWeight = style.fontWeight; if (style.fontWeight) ctx.dom.subtitleRoot.style.fontWeight = String(style.fontWeight);
if (style.fontStyle) ctx.dom.subtitleRoot.style.fontStyle = style.fontStyle; if (style.fontStyle) ctx.dom.subtitleRoot.style.fontStyle = style.fontStyle;
const knownWordColor = style.knownWordColor ?? ctx.state.knownWordColor ?? '#a6da95'; const knownWordColor = style.knownWordColor ?? ctx.state.knownWordColor ?? '#a6da95';
const nPlusOneColor = style.nPlusOneColor ?? ctx.state.nPlusOneColor ?? '#c6a0f6'; const nPlusOneColor = style.nPlusOneColor ?? ctx.state.nPlusOneColor ?? '#c6a0f6';
@@ -639,7 +639,7 @@ function renderSubtitle(data: SubtitleData | string): void {
ctx.dom.secondarySubRoot.style.color = secondaryStyle.fontColor; ctx.dom.secondarySubRoot.style.color = secondaryStyle.fontColor;
} }
if (secondaryStyle.fontWeight) { if (secondaryStyle.fontWeight) {
ctx.dom.secondarySubRoot.style.fontWeight = secondaryStyle.fontWeight; ctx.dom.secondarySubRoot.style.fontWeight = String(secondaryStyle.fontWeight);
} }
if (secondaryStyle.fontStyle) { if (secondaryStyle.fontStyle) {
ctx.dom.secondarySubRoot.style.fontStyle = secondaryStyle.fontStyle; ctx.dom.secondarySubRoot.style.fontStyle = secondaryStyle.fontStyle;

View File

@@ -274,8 +274,15 @@ export interface SubtitleStyleConfig {
fontFamily?: string; fontFamily?: string;
fontSize?: number; fontSize?: number;
fontColor?: string; fontColor?: string;
fontWeight?: string; fontWeight?: string | number;
fontStyle?: string; fontStyle?: string;
lineHeight?: string | number;
letterSpacing?: string;
wordSpacing?: string | number;
fontKerning?: string;
textRendering?: string;
textShadow?: string;
backdropFilter?: string;
backgroundColor?: string; backgroundColor?: string;
nPlusOneColor?: string; nPlusOneColor?: string;
knownWordColor?: string; knownWordColor?: string;
@@ -298,8 +305,15 @@ export interface SubtitleStyleConfig {
fontFamily?: string; fontFamily?: string;
fontSize?: number; fontSize?: number;
fontColor?: string; fontColor?: string;
fontWeight?: string; fontWeight?: string | number;
fontStyle?: string; fontStyle?: string;
lineHeight?: string | number;
letterSpacing?: string;
wordSpacing?: string | number;
fontKerning?: string;
textRendering?: string;
textShadow?: string;
backdropFilter?: string;
backgroundColor?: string; backgroundColor?: string;
}; };
} }