mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-11-10 16:46:06 -08:00
feat(dictionary): add Hachidori backend support (#266)
This commit is contained in:
1 parent
e690ffba07
commit
cbaa4626e1
143 files changed
+5564
-305
No files matched your search
@@ -22,6 +22,7 @@ export type {
|
||||
} from './definitions/shared';
|
||||
|
||||
const {
|
||||
dictionaryBackend,
|
||||
subtitlePosition,
|
||||
keybindings,
|
||||
websocket,
|
||||
@@ -57,6 +58,7 @@ const { stats } = STATS_DEFAULT_CONFIG;
|
||||
export const DEFAULT_CONFIG: ResolvedConfig = {
|
||||
subtitleSelection: { enabled: false },
|
||||
subtitleGeneration: { ...DEFAULT_SUBTITLE_GENERATION_CONFIG },
|
||||
dictionaryBackend,
|
||||
subtitlePosition,
|
||||
keybindings,
|
||||
websocket,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ResolvedConfig } from '../../types/config';
|
||||
|
||||
export const CORE_DEFAULT_CONFIG: Pick<
|
||||
ResolvedConfig,
|
||||
| 'dictionaryBackend'
|
||||
| 'subtitlePosition'
|
||||
| 'keybindings'
|
||||
| 'websocket'
|
||||
@@ -18,6 +19,7 @@ export const CORE_DEFAULT_CONFIG: Pick<
|
||||
| 'notifications'
|
||||
| 'auto_start_overlay'
|
||||
> = {
|
||||
dictionaryBackend: 'yomitan',
|
||||
subtitlePosition: { yPercent: 10 },
|
||||
keybindings: [],
|
||||
websocket: {
|
||||
|
||||
@@ -81,6 +81,13 @@ export function buildCoreConfigOptionRegistry(
|
||||
] as const;
|
||||
|
||||
return [
|
||||
{
|
||||
path: 'dictionaryBackend',
|
||||
kind: 'enum',
|
||||
enumValues: ['yomitan', 'hachidori'],
|
||||
defaultValue: defaultConfig.dictionaryBackend,
|
||||
description: 'Dictionary lookup backend. Restart SubMiner after changing this setting.',
|
||||
},
|
||||
{
|
||||
path: 'logging.level',
|
||||
kind: 'enum',
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { ConfigTemplateSection } from './shared';
|
||||
|
||||
const CORE_TEMPLATE_SECTIONS: ConfigTemplateSection[] = [
|
||||
{
|
||||
title: 'Dictionary Backend',
|
||||
description: ['Select the dictionary lookup backend: yomitan or hachidori.'],
|
||||
notes: [
|
||||
'Restart SubMiner after changing the backend. Each backend keeps separate settings and dictionaries.',
|
||||
],
|
||||
key: 'dictionaryBackend',
|
||||
},
|
||||
{
|
||||
title: 'Subtitle Selection',
|
||||
description: ['Select primary and secondary mpv subtitle tracks from the overlay.'],
|
||||
|
||||
@@ -6,6 +6,17 @@ import { asBoolean, asNumber, asString, isObject } from './shared';
|
||||
export function applyCoreDomainConfig(context: ResolveContext): void {
|
||||
const { src, resolved, warn } = context;
|
||||
|
||||
if (src.dictionaryBackend === 'yomitan' || src.dictionaryBackend === 'hachidori') {
|
||||
resolved.dictionaryBackend = src.dictionaryBackend;
|
||||
} else if (src.dictionaryBackend !== undefined) {
|
||||
warn(
|
||||
'dictionaryBackend',
|
||||
src.dictionaryBackend,
|
||||
resolved.dictionaryBackend,
|
||||
"Expected 'yomitan' or 'hachidori'.",
|
||||
);
|
||||
}
|
||||
|
||||
if (isObject(src.subtitleSelection)) {
|
||||
const enabled = asBoolean(src.subtitleSelection.enabled);
|
||||
if (enabled !== undefined) resolved.subtitleSelection.enabled = enabled;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { resolveConfig } from '../resolve';
|
||||
import { buildConfigSettingsRegistry } from '../settings/registry';
|
||||
import { createResolveContext } from './context';
|
||||
import { applyCoreDomainConfig } from './core-domains';
|
||||
|
||||
test('dictionary backend defaults to Yomitan and accepts Hachidori', () => {
|
||||
assert.equal(resolveConfig({}).resolved.dictionaryBackend, 'yomitan');
|
||||
const { resolved, warnings } = resolveConfig({ dictionaryBackend: 'hachidori' });
|
||||
assert.equal(resolved.dictionaryBackend, 'hachidori');
|
||||
assert.deepEqual(warnings, []);
|
||||
const field = buildConfigSettingsRegistry(resolved).find(
|
||||
(entry) => entry.configPath === 'dictionaryBackend',
|
||||
);
|
||||
assert.equal(field?.restartBehavior, 'restart');
|
||||
assert.deepEqual(field?.enumValues, ['yomitan', 'hachidori']);
|
||||
assert.equal(field?.category, 'integrations');
|
||||
});
|
||||
|
||||
test('unknown dictionary backend values warn and preserve the default', () => {
|
||||
for (const dictionaryBackend of ['unknown', '', null, true, {}]) {
|
||||
const { context, warnings } = createResolveContext({});
|
||||
context.src.dictionaryBackend = dictionaryBackend;
|
||||
applyCoreDomainConfig(context);
|
||||
assert.equal(context.resolved.dictionaryBackend, 'yomitan');
|
||||
assert.equal(warnings.length, 1);
|
||||
assert.equal(warnings[0]?.path, 'dictionaryBackend');
|
||||
}
|
||||
});
|
||||
@@ -146,6 +146,7 @@ const SECTION_ORDER = new Map<string, number>(
|
||||
'Discord Rich Presence',
|
||||
'Jellyfin',
|
||||
'Texthooker',
|
||||
'Dictionary Lookup',
|
||||
'Yomitan',
|
||||
'Stats dashboard',
|
||||
'Startup warmups',
|
||||
@@ -228,8 +229,8 @@ const LABEL_OVERRIDES: Record<string, string> = {
|
||||
'shortcuts.openCharacterDictionaryManager': 'Open Character Dictionary Manager',
|
||||
'subtitleSidebar.pauseVideoOnHover': 'Pause Video On Hover - Sidebar',
|
||||
'subtitleStyle.autoPauseVideoOnHover': 'Pause Video On Hover - Subtitles',
|
||||
'subtitleStyle.autoPauseVideoOnYomitanPopup': 'Pause Video On Yomitan Popup',
|
||||
'subtitleStyle.primaryVisibleOnYomitanPopup': 'Keep Primary Visible On Yomitan Popup',
|
||||
'subtitleStyle.autoPauseVideoOnYomitanPopup': 'Pause Video On Dictionary Popup',
|
||||
'subtitleStyle.primaryVisibleOnYomitanPopup': 'Keep Primary Visible On Dictionary Popup',
|
||||
'subtitleStyle.primaryDefaultMode': 'Primary Subtitle Visibility Mode',
|
||||
'subtitleStyle.frequencyDictionary.mode': 'Frequency Mode',
|
||||
'subtitleStyle.css': 'CSS Declarations',
|
||||
@@ -270,7 +271,7 @@ const DESCRIPTION_OVERRIDES: Record<string, string> = {
|
||||
'subtitleSidebar.css':
|
||||
'CSS declarations applied to the subtitle sidebar. Includes color, background-color, all font properties, and sidebar CSS variables.',
|
||||
'subtitleStyle.primaryVisibleOnYomitanPopup':
|
||||
'When primary subtitles are in hover mode, keep the primary subtitle bar visible while a Yomitan popup is open.',
|
||||
'When primary subtitles are in hover mode, keep the primary subtitle bar visible while a dictionary popup is open.',
|
||||
'websocket.enabled':
|
||||
'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':
|
||||
@@ -334,6 +335,9 @@ function humanizePath(path: string): string {
|
||||
}
|
||||
|
||||
function categoryAndSection(path: string): { category: ConfigSettingsCategory; section: string } {
|
||||
if (path === 'dictionaryBackend') {
|
||||
return { category: 'integrations', section: 'Dictionary Lookup' };
|
||||
}
|
||||
if (
|
||||
path === 'subtitleStyle.autoPauseVideoOnHover' ||
|
||||
path === 'subtitleStyle.autoPauseVideoOnYomitanPopup' ||
|
||||
|
||||
Reference in new issue
Block a user