mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-06 19:57:26 -08:00
fix(core): recopy Yomitan extension when patched scripts drift
This commit is contained in:
53
src/core/services/yomitan-extension-copy.ts
Normal file
53
src/core/services/yomitan-extension-copy.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const YOMITAN_SYNC_SCRIPT_PATHS = [
|
||||
path.join('js', 'app', 'popup.js'),
|
||||
path.join('js', 'display', 'popup-main.js'),
|
||||
path.join('js', 'display', 'display.js'),
|
||||
path.join('js', 'display', 'display-audio.js'),
|
||||
];
|
||||
|
||||
function readManifestVersion(manifestPath: string): string | null {
|
||||
try {
|
||||
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as { version?: unknown };
|
||||
return typeof parsed.version === 'string' ? parsed.version : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function areFilesEqual(sourcePath: string, targetPath: string): boolean {
|
||||
if (!fs.existsSync(sourcePath) || !fs.existsSync(targetPath)) return false;
|
||||
try {
|
||||
return fs.readFileSync(sourcePath).equals(fs.readFileSync(targetPath));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function shouldCopyYomitanExtension(sourceDir: string, targetDir: string): boolean {
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const sourceManifest = path.join(sourceDir, 'manifest.json');
|
||||
const targetManifest = path.join(targetDir, 'manifest.json');
|
||||
if (!fs.existsSync(sourceManifest) || !fs.existsSync(targetManifest)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const sourceVersion = readManifestVersion(sourceManifest);
|
||||
const targetVersion = readManifestVersion(targetManifest);
|
||||
if (sourceVersion === null || targetVersion === null || sourceVersion !== targetVersion) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const relativePath of YOMITAN_SYNC_SCRIPT_PATHS) {
|
||||
if (!areFilesEqual(path.join(sourceDir, relativePath), path.join(targetDir, relativePath))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
52
src/core/services/yomitan-extension-loader.test.ts
Normal file
52
src/core/services/yomitan-extension-loader.test.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
|
||||
import { shouldCopyYomitanExtension } from './yomitan-extension-copy';
|
||||
|
||||
function writeFile(filePath: string, content: string): void {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
fs.writeFileSync(filePath, content, 'utf-8');
|
||||
}
|
||||
|
||||
test('shouldCopyYomitanExtension detects popup runtime script drift', () => {
|
||||
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'yomitan-copy-test-'));
|
||||
const sourceDir = path.join(tempRoot, 'source');
|
||||
const targetDir = path.join(tempRoot, 'target');
|
||||
|
||||
writeFile(path.join(sourceDir, 'manifest.json'), JSON.stringify({ version: '1.0.0' }));
|
||||
writeFile(path.join(targetDir, 'manifest.json'), JSON.stringify({ version: '1.0.0' }));
|
||||
|
||||
writeFile(path.join(sourceDir, 'js', 'app', 'popup.js'), 'same-popup-script');
|
||||
writeFile(path.join(targetDir, 'js', 'app', 'popup.js'), 'same-popup-script');
|
||||
|
||||
writeFile(path.join(sourceDir, 'js', 'display', 'popup-main.js'), 'source-popup-main');
|
||||
writeFile(path.join(targetDir, 'js', 'display', 'popup-main.js'), 'target-popup-main');
|
||||
|
||||
assert.equal(shouldCopyYomitanExtension(sourceDir, targetDir), true);
|
||||
});
|
||||
|
||||
test('shouldCopyYomitanExtension skips copy when versions and watched scripts match', () => {
|
||||
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'yomitan-copy-test-'));
|
||||
const sourceDir = path.join(tempRoot, 'source');
|
||||
const targetDir = path.join(tempRoot, 'target');
|
||||
|
||||
writeFile(path.join(sourceDir, 'manifest.json'), JSON.stringify({ version: '1.0.0' }));
|
||||
writeFile(path.join(targetDir, 'manifest.json'), JSON.stringify({ version: '1.0.0' }));
|
||||
|
||||
writeFile(path.join(sourceDir, 'js', 'app', 'popup.js'), 'same-popup-script');
|
||||
writeFile(path.join(targetDir, 'js', 'app', 'popup.js'), 'same-popup-script');
|
||||
|
||||
writeFile(path.join(sourceDir, 'js', 'display', 'popup-main.js'), 'same-popup-main');
|
||||
writeFile(path.join(targetDir, 'js', 'display', 'popup-main.js'), 'same-popup-main');
|
||||
|
||||
writeFile(path.join(sourceDir, 'js', 'display', 'display.js'), 'same-display');
|
||||
writeFile(path.join(targetDir, 'js', 'display', 'display.js'), 'same-display');
|
||||
|
||||
writeFile(path.join(sourceDir, 'js', 'display', 'display-audio.js'), 'same-display-audio');
|
||||
writeFile(path.join(targetDir, 'js', 'display', 'display-audio.js'), 'same-display-audio');
|
||||
|
||||
assert.equal(shouldCopyYomitanExtension(sourceDir, targetDir), false);
|
||||
});
|
||||
@@ -2,6 +2,7 @@ import { BrowserWindow, Extension, session } from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createLogger } from '../../logger';
|
||||
import { shouldCopyYomitanExtension } from './yomitan-extension-copy';
|
||||
|
||||
const logger = createLogger('main:yomitan-extension-loader');
|
||||
|
||||
@@ -22,27 +23,7 @@ function ensureExtensionCopy(sourceDir: string, userDataPath: string): string {
|
||||
const extensionsRoot = path.join(userDataPath, 'extensions');
|
||||
const targetDir = path.join(extensionsRoot, 'yomitan');
|
||||
|
||||
const sourceManifest = path.join(sourceDir, 'manifest.json');
|
||||
const targetManifest = path.join(targetDir, 'manifest.json');
|
||||
|
||||
let shouldCopy = !fs.existsSync(targetDir);
|
||||
if (!shouldCopy && fs.existsSync(sourceManifest) && fs.existsSync(targetManifest)) {
|
||||
try {
|
||||
const sourceVersion = (
|
||||
JSON.parse(fs.readFileSync(sourceManifest, 'utf-8')) as {
|
||||
version: string;
|
||||
}
|
||||
).version;
|
||||
const targetVersion = (
|
||||
JSON.parse(fs.readFileSync(targetManifest, 'utf-8')) as {
|
||||
version: string;
|
||||
}
|
||||
).version;
|
||||
shouldCopy = sourceVersion !== targetVersion;
|
||||
} catch {
|
||||
shouldCopy = true;
|
||||
}
|
||||
}
|
||||
const shouldCopy = shouldCopyYomitanExtension(sourceDir, targetDir);
|
||||
|
||||
if (shouldCopy) {
|
||||
fs.mkdirSync(extensionsRoot, { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user