mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-20 12:11:28 -07:00
Expand Yomitan external profile tilde paths to home directory
- Normalize `yomitan.externalProfilePath` so `~` and `~/...` resolve to the current user home directory - Add coverage for tilde expansion in integration config tests - Update Yomitan config docs and tighten settings opener test assertion
This commit is contained in:
@@ -112,6 +112,7 @@ The configuration file includes several main sections:
|
|||||||
- [**Jimaku**](#jimaku) - Jimaku API configuration and defaults
|
- [**Jimaku**](#jimaku) - Jimaku API configuration and defaults
|
||||||
- [**Auto Subtitle Sync**](#auto-subtitle-sync) - Sync current subtitle with `alass`/`ffsubsync`
|
- [**Auto Subtitle Sync**](#auto-subtitle-sync) - Sync current subtitle with `alass`/`ffsubsync`
|
||||||
- [**AniList**](#anilist) - Optional post-watch progress updates
|
- [**AniList**](#anilist) - Optional post-watch progress updates
|
||||||
|
- [**Yomitan**](#yomitan) - Reuse an external read-only Yomitan profile via `yomitan.externalProfilePath`
|
||||||
- [**Jellyfin**](#jellyfin) - Optional Jellyfin auth, library listing, and playback launch
|
- [**Jellyfin**](#jellyfin) - Optional Jellyfin auth, library listing, and playback launch
|
||||||
- [**Discord Rich Presence**](#discord-rich-presence) - Optional Discord activity card updates
|
- [**Discord Rich Presence**](#discord-rich-presence) - Optional Discord activity card updates
|
||||||
- [**Immersion Tracking**](#immersion-tracking) - Track subtitle sessions and mining activity in SQLite
|
- [**Immersion Tracking**](#immersion-tracking) - Track subtitle sessions and mining activity in SQLite
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
|
import * as os from 'node:os';
|
||||||
|
import * as path from 'node:path';
|
||||||
import { ResolveContext } from './context';
|
import { ResolveContext } from './context';
|
||||||
import { asBoolean, asNumber, asString, isObject } from './shared';
|
import { asBoolean, asNumber, asString, isObject } from './shared';
|
||||||
|
|
||||||
|
function normalizeExternalProfilePath(value: string): string {
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if (trimmed === '~') {
|
||||||
|
return os.homedir();
|
||||||
|
}
|
||||||
|
if (trimmed.startsWith('~/') || trimmed.startsWith('~\\')) {
|
||||||
|
return path.join(os.homedir(), trimmed.slice(2));
|
||||||
|
}
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
export function applyIntegrationConfig(context: ResolveContext): void {
|
export function applyIntegrationConfig(context: ResolveContext): void {
|
||||||
const { src, resolved, warn } = context;
|
const { src, resolved, warn } = context;
|
||||||
|
|
||||||
@@ -202,7 +215,7 @@ export function applyIntegrationConfig(context: ResolveContext): void {
|
|||||||
if (isObject(src.yomitan)) {
|
if (isObject(src.yomitan)) {
|
||||||
const externalProfilePath = asString(src.yomitan.externalProfilePath);
|
const externalProfilePath = asString(src.yomitan.externalProfilePath);
|
||||||
if (externalProfilePath !== undefined) {
|
if (externalProfilePath !== undefined) {
|
||||||
resolved.yomitan.externalProfilePath = externalProfilePath.trim();
|
resolved.yomitan.externalProfilePath = normalizeExternalProfilePath(externalProfilePath);
|
||||||
} else if (src.yomitan.externalProfilePath !== undefined) {
|
} else if (src.yomitan.externalProfilePath !== undefined) {
|
||||||
warn(
|
warn(
|
||||||
'yomitan.externalProfilePath',
|
'yomitan.externalProfilePath',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
|
import * as os from 'node:os';
|
||||||
import { createResolveContext } from './context';
|
import { createResolveContext } from './context';
|
||||||
import { applyIntegrationConfig } from './integrations';
|
import { applyIntegrationConfig } from './integrations';
|
||||||
|
|
||||||
@@ -127,3 +128,16 @@ test('yomitan externalProfilePath is trimmed and invalid values warn', () => {
|
|||||||
assert.equal(invalid.context.resolved.yomitan.externalProfilePath, '');
|
assert.equal(invalid.context.resolved.yomitan.externalProfilePath, '');
|
||||||
assert.ok(invalid.warnings.some((warning) => warning.path === 'yomitan.externalProfilePath'));
|
assert.ok(invalid.warnings.some((warning) => warning.path === 'yomitan.externalProfilePath'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('yomitan externalProfilePath expands leading tilde to the current home directory', () => {
|
||||||
|
const homeDir = os.homedir();
|
||||||
|
const { context } = createResolveContext({
|
||||||
|
yomitan: {
|
||||||
|
externalProfilePath: '~/.config/gsm_overlay',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
applyIntegrationConfig(context);
|
||||||
|
|
||||||
|
assert.equal(context.resolved.yomitan.externalProfilePath, `${homeDir}/.config/gsm_overlay`);
|
||||||
|
});
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ test('yomitan opener warns when extension cannot be loaded', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('yomitan opener opens settings window when extension is available', async () => {
|
test('yomitan opener opens settings window when extension is available', async () => {
|
||||||
let opened = false;
|
let forwardedSession: { id: string } | null | undefined;
|
||||||
const yomitanSession = { id: 'session' };
|
const yomitanSession = { id: 'session' };
|
||||||
const openSettings = createOpenYomitanSettingsHandler({
|
const openSettings = createOpenYomitanSettingsHandler({
|
||||||
ensureYomitanExtensionLoaded: async () => ({ id: 'ext' }),
|
ensureYomitanExtensionLoaded: async () => ({ id: 'ext' }),
|
||||||
openYomitanSettingsWindow: ({ yomitanSession: forwardedSession }) => {
|
openYomitanSettingsWindow: ({ yomitanSession: nextSession }) => {
|
||||||
opened = (forwardedSession as { id: string } | null)?.id === 'session';
|
forwardedSession = nextSession as { id: string } | null;
|
||||||
},
|
},
|
||||||
getExistingWindow: () => null,
|
getExistingWindow: () => null,
|
||||||
setWindow: () => {},
|
setWindow: () => {},
|
||||||
@@ -39,5 +39,5 @@ test('yomitan opener opens settings window when extension is available', async (
|
|||||||
openSettings();
|
openSettings();
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
assert.equal(opened, true);
|
assert.equal(forwardedSession, yomitanSession);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user