fix: 设置页脚本因重复声明 xt 整体加载失败(服务商选不了、所有设置不生效)
- settings.js 的局部变量改名为 api,避开 contextBridge 暴露的不可重声明全局 xt - dev-mock 按 contextBridge 的方式定义 xt,浏览器预览也能暴露同类问题 - 加测试:渲染脚本禁止在顶层声明 xt - 版本 0.1.2 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ad83db6e7f
commit
1ae69ab95e
5 files changed
+20
-11
No files matched your search
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "xtranslate",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "xtranslate",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"dependencies": {
|
||||
"koffi": "3.3.2"
|
||||
},
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "xtranslate",
|
||||
"productName": "Xtranslate",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"description": "中英互译输入法:热键呼出,打字即译,口语化",
|
||||
"main": "src/main/main.js",
|
||||
"private": true,
|
||||
|
||||
@@ -10,7 +10,8 @@ if (!window.xt) {
|
||||
const canned = { '我先撤了哈,明天见': "I'm heading out, see you tomorrow!", 'No worries, take your time!': '没事没事,你慢慢来!' };
|
||||
const timers = {};
|
||||
const merge = (a, b) => { for (const k in b) a[k] = b[k] && typeof b[k] === 'object' && !Array.isArray(b[k]) ? merge({ ...(a[k] || {}) }, b[k]) : b[k]; return a; };
|
||||
window.xt = {
|
||||
// 和 contextBridge 一样定义成不可重声明的全局,页面里再写 const xt 会像在 Electron 里一样报错
|
||||
Object.defineProperty(window, 'xt', { configurable: false, enumerable: true, writable: false, value: {
|
||||
translate({ id, text, engine }) {
|
||||
const full = canned[text.trim()] || (/[一-鿿]/.test(text) ? `(mock EN) ${text}` : `(模拟中文)${text}`);
|
||||
if ((engine || cfg.engine) === 'llm' && !cfg.llm.apiKeySet) return Promise.reject(new Error('还没填大模型的 API Key,去设置里填一下'));
|
||||
@@ -49,6 +50,6 @@ if (!window.xt) {
|
||||
: { ok: true, sample: "I'm heading out, see you tomorrow!", ms: 420 },
|
||||
openSettings: () => console.log('[mock] openSettings'),
|
||||
onConfigChanged: (cb) => listeners.config.push(cb),
|
||||
};
|
||||
} });
|
||||
document.documentElement.style.background = '#8a93a3';
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const xt = window.xt;
|
||||
const api = window.xt; // 不能叫 xt:contextBridge 已把 xt 定义为不可重声明的全局
|
||||
let providers = [];
|
||||
let cfg = null;
|
||||
|
||||
@@ -14,7 +14,7 @@ function setResult(el, text, kind) {
|
||||
|
||||
async function save(partial) {
|
||||
try {
|
||||
cfg = await xt.setConfig(partial);
|
||||
cfg = await api.setConfig(partial);
|
||||
render();
|
||||
return true;
|
||||
} catch (e) {
|
||||
@@ -92,7 +92,7 @@ for (const btn of document.querySelectorAll('[data-test]')) {
|
||||
await save(partial);
|
||||
$('llm-key').value = '';
|
||||
}
|
||||
const r = await xt.testEngine({ engine });
|
||||
const r = await api.testEngine({ engine });
|
||||
if (r.ok) setResult(out, `✓ ${r.sample}(${r.ms} ms)`, 'ok');
|
||||
else setResult(out, r.error || '失败', 'err');
|
||||
} catch (e) {
|
||||
@@ -160,11 +160,11 @@ hk.addEventListener('keydown', async (e) => {
|
||||
}
|
||||
});
|
||||
|
||||
xt.onConfigChanged((c) => { cfg = c; render(); });
|
||||
api.onConfigChanged((c) => { cfg = c; render(); });
|
||||
|
||||
(async () => {
|
||||
providers = await xt.getProviders();
|
||||
providers = await api.getProviders();
|
||||
$('llm-provider').replaceChildren(...providers.map((p) => Object.assign(document.createElement('option'), { value: p.id, textContent: p.name })));
|
||||
cfg = await xt.getConfig();
|
||||
cfg = await api.getConfig();
|
||||
render();
|
||||
})();
|
||||
@@ -26,3 +26,11 @@ test('src 下所有 JS 文件语法正确', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('渲染进程脚本不在顶层声明 xt(会与 contextBridge 暴露的全局冲突,整个脚本加载失败)', () => {
|
||||
const dir = path.join(__dirname, '..', 'src', 'renderer');
|
||||
for (const name of fs.readdirSync(dir).filter((n) => n.endsWith('.js') && n !== 'dev-mock.js')) {
|
||||
const src = fs.readFileSync(path.join(dir, name), 'utf8');
|
||||
assert.doesNotMatch(src, /^(const|let|var|function|class)\s+xt\b/m, name);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user