mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-11-11 04:46:07 -08:00
feat(subtitles): add regex subtitle filters with built-in presets (#318)
- Add `subtitleFilter` config with four presets: parentheses, brackets, speaker prefix and music symbols. Custom regex rules run after the presets. - Filter primary text where it enters the app (live `sub-text` and parsed cues), so the overlay, sidebar, mining and stats all get the same filtered text. - Changes hot-reload: the current line is read again and the active track is parsed again, using the filter config as the prefetch parse key. - Add a custom rule editor in Settings under Behavior → Subtitle Filters that checks patterns as you type. - Update the config example, the configuration docs and the architecture domains doc, and add a changelog fragment.
This commit is contained in:
1 parent
848a6c4021
commit
fa3051f9cb
28 files changed
+740
-11
No files matched your search
@@ -6,6 +6,10 @@ import type {
|
||||
ConfigSettingsField,
|
||||
} from '../../types/settings';
|
||||
import { CONFIG_OPTION_REGISTRY, DEFAULT_CONFIG } from '../definitions';
|
||||
import {
|
||||
SUBTITLE_FILTER_PRESET_IDS,
|
||||
SUBTITLE_FILTER_PRESETS,
|
||||
} from '../../shared/subtitle-text-filter';
|
||||
import {
|
||||
getSubtitleCssManagedConfigPaths,
|
||||
getSubtitleCssScopeForPath,
|
||||
@@ -127,6 +131,7 @@ const SECTION_ORDER = new Map<string, number>(
|
||||
'Subtitle Sidebar Appearance',
|
||||
'Playback Behavior',
|
||||
'Subtitle Behavior',
|
||||
'Subtitle Filters',
|
||||
'Subtitle Sidebar Behavior',
|
||||
'YouTube Playback Settings',
|
||||
'mpv Playback',
|
||||
@@ -203,6 +208,7 @@ const PATH_ORDER = new Map<string, number>(
|
||||
'logging.files.app',
|
||||
'logging.files.launcher',
|
||||
'logging.files.mpv',
|
||||
...SUBTITLE_FILTER_PRESET_IDS.map((id) => `subtitleFilter.presets.${id}`),
|
||||
].map((path, index) => [path, index]),
|
||||
);
|
||||
|
||||
@@ -253,6 +259,12 @@ const LABEL_OVERRIDES: Record<string, string> = {
|
||||
'ankiConnect.media.mirrorMpvVolume': 'Mirror mpv Volume',
|
||||
'ankiConnect.media.reviewTiming': 'Review Media Timing',
|
||||
'discordPresence.updateIntervalMs': 'Update Interval (ms)',
|
||||
...Object.fromEntries(
|
||||
SUBTITLE_FILTER_PRESET_IDS.map((id) => [
|
||||
`subtitleFilter.presets.${id}`,
|
||||
SUBTITLE_FILTER_PRESETS[id].label,
|
||||
]),
|
||||
),
|
||||
};
|
||||
|
||||
const DESCRIPTION_OVERRIDES: Record<string, string> = {
|
||||
@@ -280,6 +292,8 @@ const DESCRIPTION_OVERRIDES: Record<string, string> = {
|
||||
'Built-in subtitle WebSocket server mode. Auto starts the built-in server only when mpv_websocket is not detected; otherwise it defers to the plugin.',
|
||||
'discordPresence.updateIntervalMs':
|
||||
'Minimum interval between presence payload updates, in milliseconds.',
|
||||
'subtitleFilter.customRules':
|
||||
'Your own regex rules, applied in order after the presets. ^ and $ match each line. Leave the replacement empty to remove the match.',
|
||||
};
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
@@ -353,6 +367,9 @@ function categoryAndSection(path: string): { category: ConfigSettingsCategory; s
|
||||
if (path === 'subtitleStyle.preserveLineBreaks') {
|
||||
return { category: 'behavior', section: 'Subtitle Behavior' };
|
||||
}
|
||||
if (path.startsWith('subtitleFilter.')) {
|
||||
return { category: 'behavior', section: 'Subtitle Filters' };
|
||||
}
|
||||
if (
|
||||
path === 'ankiConnect.knownWords.addMinedWordsImmediately' ||
|
||||
path === 'ankiConnect.knownWords.decks' ||
|
||||
@@ -557,6 +574,7 @@ function controlForPath(path: string, value: unknown): ConfigSettingsControl {
|
||||
if (path.startsWith('subtitleStyle.jlptColors.')) return 'color';
|
||||
if (path.startsWith('subtitleStyle.knownWordMaturityColors.')) return 'color';
|
||||
if (path === 'subtitleStyle.frequencyDictionary.bandedColors') return 'color-list';
|
||||
if (path === 'subtitleFilter.customRules') return 'subtitle-filter-rules';
|
||||
if (OPTION_BY_PATH.get(path)?.enumValues?.length) return 'select';
|
||||
if (JSON_OBJECT_FIELDS.has(path)) return 'json';
|
||||
if (Array.isArray(value)) return 'string-list';
|
||||
|
||||
Reference in new issue
Block a user