mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-04-10 16:19:24 -07:00
Add read-only external Yomitan profile support
- add `yomitan.externalProfilePath` config and default/template wiring - load Yomitan from an external Electron profile/session when configured - disable SubMiner Yomitan writes/settings UI in external-profile mode and update docs/tests
This commit is contained in:
@@ -30,6 +30,7 @@ test('loads defaults when config is missing', () => {
|
||||
assert.equal(config.anilist.characterDictionary.collapsibleSections.description, false);
|
||||
assert.equal(config.anilist.characterDictionary.collapsibleSections.characterInformation, false);
|
||||
assert.equal(config.anilist.characterDictionary.collapsibleSections.voicedBy, false);
|
||||
assert.equal(config.yomitan.externalProfilePath, '');
|
||||
assert.equal(config.jellyfin.remoteControlEnabled, true);
|
||||
assert.equal(config.jellyfin.remoteControlAutoConnect, true);
|
||||
assert.equal(config.jellyfin.autoAnnounce, false);
|
||||
|
||||
@@ -32,7 +32,7 @@ const {
|
||||
startupWarmups,
|
||||
auto_start_overlay,
|
||||
} = CORE_DEFAULT_CONFIG;
|
||||
const { ankiConnect, jimaku, anilist, jellyfin, discordPresence, ai, youtubeSubgen } =
|
||||
const { ankiConnect, jimaku, anilist, yomitan, jellyfin, discordPresence, ai, youtubeSubgen } =
|
||||
INTEGRATIONS_DEFAULT_CONFIG;
|
||||
const { subtitleStyle } = SUBTITLE_DEFAULT_CONFIG;
|
||||
const { immersionTracking } = IMMERSION_DEFAULT_CONFIG;
|
||||
@@ -54,6 +54,7 @@ export const DEFAULT_CONFIG: ResolvedConfig = {
|
||||
auto_start_overlay,
|
||||
jimaku,
|
||||
anilist,
|
||||
yomitan,
|
||||
jellyfin,
|
||||
discordPresence,
|
||||
ai,
|
||||
|
||||
@@ -2,7 +2,14 @@ import { ResolvedConfig } from '../../types';
|
||||
|
||||
export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
|
||||
ResolvedConfig,
|
||||
'ankiConnect' | 'jimaku' | 'anilist' | 'jellyfin' | 'discordPresence' | 'ai' | 'youtubeSubgen'
|
||||
| 'ankiConnect'
|
||||
| 'jimaku'
|
||||
| 'anilist'
|
||||
| 'yomitan'
|
||||
| 'jellyfin'
|
||||
| 'discordPresence'
|
||||
| 'ai'
|
||||
| 'youtubeSubgen'
|
||||
> = {
|
||||
ankiConnect: {
|
||||
enabled: false,
|
||||
@@ -94,6 +101,9 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
|
||||
},
|
||||
},
|
||||
},
|
||||
yomitan: {
|
||||
externalProfilePath: '',
|
||||
},
|
||||
jellyfin: {
|
||||
enabled: false,
|
||||
serverUrl: '',
|
||||
|
||||
@@ -27,6 +27,7 @@ test('config option registry includes critical paths and has unique entries', ()
|
||||
'ankiConnect.enabled',
|
||||
'anilist.characterDictionary.enabled',
|
||||
'anilist.characterDictionary.collapsibleSections.description',
|
||||
'yomitan.externalProfilePath',
|
||||
'immersionTracking.enabled',
|
||||
]) {
|
||||
assert.ok(paths.includes(requiredPath), `missing config path: ${requiredPath}`);
|
||||
@@ -44,6 +45,7 @@ test('config template sections include expected domains and unique keys', () =>
|
||||
'startupWarmups',
|
||||
'subtitleStyle',
|
||||
'ankiConnect',
|
||||
'yomitan',
|
||||
'immersionTracking',
|
||||
];
|
||||
|
||||
|
||||
@@ -211,6 +211,13 @@ export function buildIntegrationConfigOptionRegistry(
|
||||
description:
|
||||
'Open the Voiced by section by default in character dictionary glossary entries.',
|
||||
},
|
||||
{
|
||||
path: 'yomitan.externalProfilePath',
|
||||
kind: 'string',
|
||||
defaultValue: defaultConfig.yomitan.externalProfilePath,
|
||||
description:
|
||||
'Optional external Yomitan Electron profile path to use in read-only mode for shared dictionaries/settings.',
|
||||
},
|
||||
{
|
||||
path: 'jellyfin.enabled',
|
||||
kind: 'boolean',
|
||||
|
||||
@@ -137,6 +137,15 @@ const INTEGRATION_TEMPLATE_SECTIONS: ConfigTemplateSection[] = [
|
||||
],
|
||||
key: 'anilist',
|
||||
},
|
||||
{
|
||||
title: 'Yomitan',
|
||||
description: [
|
||||
'Optional external Yomitan profile integration.',
|
||||
'Setting yomitan.externalProfilePath switches SubMiner to read-only external-profile mode.',
|
||||
'In external-profile mode SubMiner will not import, delete, or modify Yomitan dictionaries/settings.',
|
||||
],
|
||||
key: 'yomitan',
|
||||
},
|
||||
{
|
||||
title: 'Jellyfin',
|
||||
description: [
|
||||
|
||||
@@ -199,6 +199,22 @@ export function applyIntegrationConfig(context: ResolveContext): void {
|
||||
}
|
||||
}
|
||||
|
||||
if (isObject(src.yomitan)) {
|
||||
const externalProfilePath = asString(src.yomitan.externalProfilePath);
|
||||
if (externalProfilePath !== undefined) {
|
||||
resolved.yomitan.externalProfilePath = externalProfilePath.trim();
|
||||
} else if (src.yomitan.externalProfilePath !== undefined) {
|
||||
warn(
|
||||
'yomitan.externalProfilePath',
|
||||
src.yomitan.externalProfilePath,
|
||||
resolved.yomitan.externalProfilePath,
|
||||
'Expected string.',
|
||||
);
|
||||
}
|
||||
} else if (src.yomitan !== undefined) {
|
||||
warn('yomitan', src.yomitan, resolved.yomitan, 'Expected object.');
|
||||
}
|
||||
|
||||
if (isObject(src.jellyfin)) {
|
||||
const enabled = asBoolean(src.jellyfin.enabled);
|
||||
if (enabled !== undefined) {
|
||||
|
||||
@@ -104,3 +104,26 @@ test('anilist character dictionary fields are parsed, clamped, and enum-validate
|
||||
warnedPaths.includes('anilist.characterDictionary.collapsibleSections.characterInformation'),
|
||||
);
|
||||
});
|
||||
|
||||
test('yomitan externalProfilePath is trimmed and invalid values warn', () => {
|
||||
const { context, warnings } = createResolveContext({
|
||||
yomitan: {
|
||||
externalProfilePath: ' /tmp/gsm-profile ',
|
||||
},
|
||||
});
|
||||
|
||||
applyIntegrationConfig(context);
|
||||
|
||||
assert.equal(context.resolved.yomitan.externalProfilePath, '/tmp/gsm-profile');
|
||||
|
||||
const invalid = createResolveContext({
|
||||
yomitan: {
|
||||
externalProfilePath: 42 as never,
|
||||
},
|
||||
});
|
||||
|
||||
applyIntegrationConfig(invalid.context);
|
||||
|
||||
assert.equal(invalid.context.resolved.yomitan.externalProfilePath, '');
|
||||
assert.ok(invalid.warnings.some((warning) => warning.path === 'yomitan.externalProfilePath'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user