translime-sdk 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -0
- package/dist/index.cjs +111 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +93 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +111 -0
- package/dist/index.js.map +1 -0
- package/dist/preview/settings.scss +86 -0
- package/dist/preview-mock.cjs +253 -0
- package/dist/preview-mock.cjs.map +1 -0
- package/dist/preview-mock.js +253 -0
- package/dist/preview-mock.js.map +1 -0
- package/dist/preview-template.html +13 -0
- package/dist/preview.cjs +3607 -0
- package/dist/preview.cjs.map +1 -0
- package/dist/preview.js +3589 -0
- package/dist/preview.js.map +1 -0
- package/dist/translime-sdk.css +1224 -0
- package/dist/vite-plugin.cjs +196 -0
- package/dist/vite-plugin.cjs.map +1 -0
- package/dist/vite-plugin.d.cts +22 -0
- package/dist/vite-plugin.d.ts +22 -0
- package/dist/vite-plugin.js +195 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +99 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const STORAGE_PREFIX = "translime-preview-settings:";
|
|
4
|
+
function createMockIpc() {
|
|
5
|
+
return {
|
|
6
|
+
invoke: async (channel, ...args) => {
|
|
7
|
+
console.log("[Preview Mock] ipc.invoke:", channel, args);
|
|
8
|
+
return null;
|
|
9
|
+
},
|
|
10
|
+
send: (channel, ...args) => {
|
|
11
|
+
console.log("[Preview Mock] ipc.send:", channel, args);
|
|
12
|
+
},
|
|
13
|
+
on: (channel, callback) => {
|
|
14
|
+
console.log("[Preview Mock] ipc.on registered:", channel);
|
|
15
|
+
return () => {
|
|
16
|
+
console.log("[Preview Mock] ipc.on removed:", channel);
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
once: (channel, callback) => {
|
|
20
|
+
console.log("[Preview Mock] ipc.once registered:", channel);
|
|
21
|
+
},
|
|
22
|
+
removeListener: (channel, callback) => {
|
|
23
|
+
console.log("[Preview Mock] ipc.removeListener:", channel);
|
|
24
|
+
},
|
|
25
|
+
removeAllListeners: (channel) => {
|
|
26
|
+
console.log("[Preview Mock] ipc.removeAllListeners:", channel);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function createMockDialog() {
|
|
31
|
+
return {
|
|
32
|
+
showOpenDialog: async (options) => {
|
|
33
|
+
console.log("[Preview Mock] showOpenDialog:", options);
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
const input = document.createElement("input");
|
|
36
|
+
input.type = "file";
|
|
37
|
+
if (options?.properties?.includes("openDirectory")) {
|
|
38
|
+
input.webkitdirectory = true;
|
|
39
|
+
}
|
|
40
|
+
if (options?.properties?.includes("multiSelections")) {
|
|
41
|
+
input.multiple = true;
|
|
42
|
+
}
|
|
43
|
+
if (options?.filters) {
|
|
44
|
+
const accept = options.filters.flatMap((f) => f.extensions.map((ext) => `.${ext}`)).join(",");
|
|
45
|
+
input.accept = accept;
|
|
46
|
+
}
|
|
47
|
+
input.onchange = () => {
|
|
48
|
+
const filePaths = Array.from(input.files || []).map((f) => f.name);
|
|
49
|
+
resolve({ canceled: filePaths.length === 0, filePaths });
|
|
50
|
+
};
|
|
51
|
+
input.oncancel = () => {
|
|
52
|
+
resolve({ canceled: true, filePaths: [] });
|
|
53
|
+
};
|
|
54
|
+
input.click();
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
showSaveDialog: async (options) => {
|
|
58
|
+
console.log("[Preview Mock] showSaveDialog:", options);
|
|
59
|
+
const fileName = prompt("保存文件名:", options?.defaultPath || "file.txt");
|
|
60
|
+
return {
|
|
61
|
+
canceled: !fileName,
|
|
62
|
+
filePath: fileName || void 0
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
showMessageBox: async (options) => {
|
|
66
|
+
console.log("[Preview Mock] showMessageBox:", options);
|
|
67
|
+
const result = confirm(options?.message || "");
|
|
68
|
+
return { response: result ? 0 : 1 };
|
|
69
|
+
},
|
|
70
|
+
showErrorBox: (title, content) => {
|
|
71
|
+
console.error("[Preview Mock] showErrorBox:", title, content);
|
|
72
|
+
alert(`${title}
|
|
73
|
+
|
|
74
|
+
${content}`);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function createMockShell() {
|
|
79
|
+
return {
|
|
80
|
+
openExternal: async (url) => {
|
|
81
|
+
console.log("[Preview Mock] shell.openExternal:", url);
|
|
82
|
+
window.open(url, "_blank");
|
|
83
|
+
},
|
|
84
|
+
openPath: async (path) => {
|
|
85
|
+
console.log("[Preview Mock] shell.openPath:", path);
|
|
86
|
+
alert(`[Preview] 无法在浏览器中打开路径: ${path}`);
|
|
87
|
+
},
|
|
88
|
+
showItemInFolder: (path) => {
|
|
89
|
+
console.log("[Preview Mock] shell.showItemInFolder:", path);
|
|
90
|
+
alert(`[Preview] 无法在浏览器中显示文件夹: ${path}`);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function createMockClipboard() {
|
|
95
|
+
return {
|
|
96
|
+
readText: async () => {
|
|
97
|
+
try {
|
|
98
|
+
return await navigator.clipboard.readText();
|
|
99
|
+
} catch (e) {
|
|
100
|
+
console.warn("[Preview Mock] clipboard.readText failed:", e);
|
|
101
|
+
return "";
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
writeText: async (text) => {
|
|
105
|
+
try {
|
|
106
|
+
await navigator.clipboard.writeText(text);
|
|
107
|
+
console.log("[Preview Mock] clipboard.writeText:", text);
|
|
108
|
+
} catch (e) {
|
|
109
|
+
console.warn("[Preview Mock] clipboard.writeText failed:", e);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
readImage: async () => {
|
|
113
|
+
console.log("[Preview Mock] clipboard.readImage: not supported in preview");
|
|
114
|
+
return null;
|
|
115
|
+
},
|
|
116
|
+
writeImage: async () => {
|
|
117
|
+
console.log("[Preview Mock] clipboard.writeImage: not supported in preview");
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function createMockWindowControl() {
|
|
122
|
+
return {
|
|
123
|
+
close: (windowId) => {
|
|
124
|
+
console.log("[Preview Mock] windowControl.close:", windowId);
|
|
125
|
+
},
|
|
126
|
+
minimize: (windowId) => {
|
|
127
|
+
console.log("[Preview Mock] windowControl.minimize:", windowId);
|
|
128
|
+
},
|
|
129
|
+
maximize: (windowId) => {
|
|
130
|
+
console.log("[Preview Mock] windowControl.maximize:", windowId);
|
|
131
|
+
},
|
|
132
|
+
unmaximize: (windowId) => {
|
|
133
|
+
console.log("[Preview Mock] windowControl.unmaximize:", windowId);
|
|
134
|
+
},
|
|
135
|
+
devtools: (windowId) => {
|
|
136
|
+
console.log("[Preview Mock] windowControl.devtools:", windowId);
|
|
137
|
+
},
|
|
138
|
+
isMaximized: async (windowId) => {
|
|
139
|
+
console.log("[Preview Mock] windowControl.isMaximized:", windowId);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function createMockPluginSettings() {
|
|
145
|
+
return {
|
|
146
|
+
get: async (pluginId) => {
|
|
147
|
+
const key = `${STORAGE_PREFIX}${pluginId}`;
|
|
148
|
+
try {
|
|
149
|
+
const data = localStorage.getItem(key);
|
|
150
|
+
return data ? JSON.parse(data) : {};
|
|
151
|
+
} catch (e) {
|
|
152
|
+
console.warn("[Preview Mock] getPluginSetting parse error:", e);
|
|
153
|
+
return {};
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
set: async (pluginId, settings) => {
|
|
157
|
+
const key = `${STORAGE_PREFIX}${pluginId}`;
|
|
158
|
+
try {
|
|
159
|
+
localStorage.setItem(key, JSON.stringify(settings));
|
|
160
|
+
console.log("[Preview Mock] setPluginSetting:", pluginId, settings);
|
|
161
|
+
} catch (e) {
|
|
162
|
+
console.warn("[Preview Mock] setPluginSetting error:", e);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function createMockLogger() {
|
|
168
|
+
return {
|
|
169
|
+
log: (...args) => console.log("[Preview]", ...args),
|
|
170
|
+
info: (...args) => console.info("[Preview]", ...args),
|
|
171
|
+
warn: (...args) => console.warn("[Preview]", ...args),
|
|
172
|
+
error: (...args) => console.error("[Preview]", ...args),
|
|
173
|
+
debug: (...args) => console.debug("[Preview]", ...args)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function createMockElectron() {
|
|
177
|
+
const mockIpc = createMockIpc();
|
|
178
|
+
return {
|
|
179
|
+
useIpc: () => mockIpc,
|
|
180
|
+
dialog: createMockDialog(),
|
|
181
|
+
shell: createMockShell(),
|
|
182
|
+
clipboard: createMockClipboard(),
|
|
183
|
+
openLink: async (url) => {
|
|
184
|
+
console.log("[Preview Mock] openLink:", url);
|
|
185
|
+
window.open(url, "_blank");
|
|
186
|
+
},
|
|
187
|
+
versions: {
|
|
188
|
+
node: "preview",
|
|
189
|
+
chrome: navigator.userAgent.match(/Chrome\/([0-9.]+)/)?.[1] || "unknown",
|
|
190
|
+
electron: "preview"
|
|
191
|
+
},
|
|
192
|
+
APP_ROOT: "/preview",
|
|
193
|
+
APPDATA_PATH: "/preview/appdata"
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function createMockTs() {
|
|
197
|
+
const pluginSettings = createMockPluginSettings();
|
|
198
|
+
return {
|
|
199
|
+
getPluginSetting: pluginSettings.get,
|
|
200
|
+
setPluginSetting: pluginSettings.set,
|
|
201
|
+
windowControl: createMockWindowControl(),
|
|
202
|
+
logger: createMockLogger(),
|
|
203
|
+
net: {
|
|
204
|
+
request: async (url, options) => {
|
|
205
|
+
console.log("[Preview Mock] net.request:", url, options);
|
|
206
|
+
try {
|
|
207
|
+
const response = await fetch(url, options);
|
|
208
|
+
return {
|
|
209
|
+
ok: response.ok,
|
|
210
|
+
status: response.status,
|
|
211
|
+
data: await response.text()
|
|
212
|
+
};
|
|
213
|
+
} catch (e) {
|
|
214
|
+
return { ok: false, status: 0, error: e.message };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function initPreviewMock() {
|
|
221
|
+
if (typeof window === "undefined") {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (!window.electron) {
|
|
225
|
+
window.electron = createMockElectron();
|
|
226
|
+
console.log("[Preview Mock] window.electron injected");
|
|
227
|
+
}
|
|
228
|
+
if (!window.ts) {
|
|
229
|
+
window.ts = createMockTs();
|
|
230
|
+
console.log("[Preview Mock] window.ts injected");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function isPreviewMode() {
|
|
234
|
+
if (typeof __TRANSLIME_PREVIEW__ !== "undefined" && __TRANSLIME_PREVIEW__) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
if (typeof window !== "undefined" && !window.electron && !window.ts) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
exports.createMockClipboard = createMockClipboard;
|
|
243
|
+
exports.createMockDialog = createMockDialog;
|
|
244
|
+
exports.createMockElectron = createMockElectron;
|
|
245
|
+
exports.createMockIpc = createMockIpc;
|
|
246
|
+
exports.createMockLogger = createMockLogger;
|
|
247
|
+
exports.createMockPluginSettings = createMockPluginSettings;
|
|
248
|
+
exports.createMockShell = createMockShell;
|
|
249
|
+
exports.createMockTs = createMockTs;
|
|
250
|
+
exports.createMockWindowControl = createMockWindowControl;
|
|
251
|
+
exports.initPreviewMock = initPreviewMock;
|
|
252
|
+
exports.isPreviewMode = isPreviewMode;
|
|
253
|
+
//# sourceMappingURL=preview-mock.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-mock.cjs","sources":["../src/preview-mock.js"],"sourcesContent":["/**\n * Preview Mock 模块\n * 为 preview 模式提供 Electron API 的 mock 实现\n */\n\nconst STORAGE_PREFIX = 'translime-preview-settings:';\n\n/**\n * Mock IPC 实现\n * @returns {Object}\n */\nexport function createMockIpc() {\n return {\n invoke: async (channel, ...args) => {\n console.log('[Preview Mock] ipc.invoke:', channel, args);\n return null;\n },\n send: (channel, ...args) => {\n console.log('[Preview Mock] ipc.send:', channel, args);\n },\n on: (channel, callback) => {\n console.log('[Preview Mock] ipc.on registered:', channel);\n return () => {\n console.log('[Preview Mock] ipc.on removed:', channel);\n };\n },\n once: (channel, callback) => {\n console.log('[Preview Mock] ipc.once registered:', channel);\n },\n removeListener: (channel, callback) => {\n console.log('[Preview Mock] ipc.removeListener:', channel);\n },\n removeAllListeners: (channel) => {\n console.log('[Preview Mock] ipc.removeAllListeners:', channel);\n },\n };\n}\n\n/**\n * Mock Dialog 实现\n * @returns {Object}\n */\nexport function createMockDialog() {\n return {\n showOpenDialog: async (options) => {\n console.log('[Preview Mock] showOpenDialog:', options);\n // 在 preview 模式下,使用原生 file input 模拟\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n if (options?.properties?.includes('openDirectory')) {\n input.webkitdirectory = true;\n }\n if (options?.properties?.includes('multiSelections')) {\n input.multiple = true;\n }\n if (options?.filters) {\n const accept = options.filters\n .flatMap((f) => f.extensions.map((ext) => `.${ext}`))\n .join(',');\n input.accept = accept;\n }\n input.onchange = () => {\n const filePaths = Array.from(input.files || []).map((f) => f.name);\n resolve({ canceled: filePaths.length === 0, filePaths });\n };\n input.oncancel = () => {\n resolve({ canceled: true, filePaths: [] });\n };\n input.click();\n });\n },\n showSaveDialog: async (options) => {\n console.log('[Preview Mock] showSaveDialog:', options);\n const fileName = prompt('保存文件名:', options?.defaultPath || 'file.txt');\n return {\n canceled: !fileName,\n filePath: fileName || undefined,\n };\n },\n showMessageBox: async (options) => {\n console.log('[Preview Mock] showMessageBox:', options);\n const result = confirm(options?.message || '');\n return { response: result ? 0 : 1 };\n },\n showErrorBox: (title, content) => {\n console.error('[Preview Mock] showErrorBox:', title, content);\n alert(`${title}\\n\\n${content}`);\n },\n };\n}\n\n/**\n * Mock Shell 实现\n * @returns {Object}\n */\nexport function createMockShell() {\n return {\n openExternal: async (url) => {\n console.log('[Preview Mock] shell.openExternal:', url);\n window.open(url, '_blank');\n },\n openPath: async (path) => {\n console.log('[Preview Mock] shell.openPath:', path);\n alert(`[Preview] 无法在浏览器中打开路径: ${path}`);\n },\n showItemInFolder: (path) => {\n console.log('[Preview Mock] shell.showItemInFolder:', path);\n alert(`[Preview] 无法在浏览器中显示文件夹: ${path}`);\n },\n };\n}\n\n/**\n * Mock Clipboard 实现\n * @returns {Object}\n */\nexport function createMockClipboard() {\n return {\n readText: async () => {\n try {\n return await navigator.clipboard.readText();\n } catch (e) {\n console.warn('[Preview Mock] clipboard.readText failed:', e);\n return '';\n }\n },\n writeText: async (text) => {\n try {\n await navigator.clipboard.writeText(text);\n console.log('[Preview Mock] clipboard.writeText:', text);\n } catch (e) {\n console.warn('[Preview Mock] clipboard.writeText failed:', e);\n }\n },\n readImage: async () => {\n console.log('[Preview Mock] clipboard.readImage: not supported in preview');\n return null;\n },\n writeImage: async () => {\n console.log('[Preview Mock] clipboard.writeImage: not supported in preview');\n },\n };\n}\n\n/**\n * Mock Window Control 实现\n * @returns {Object}\n */\nexport function createMockWindowControl() {\n return {\n close: (windowId) => {\n console.log('[Preview Mock] windowControl.close:', windowId);\n },\n minimize: (windowId) => {\n console.log('[Preview Mock] windowControl.minimize:', windowId);\n },\n maximize: (windowId) => {\n console.log('[Preview Mock] windowControl.maximize:', windowId);\n },\n unmaximize: (windowId) => {\n console.log('[Preview Mock] windowControl.unmaximize:', windowId);\n },\n devtools: (windowId) => {\n console.log('[Preview Mock] windowControl.devtools:', windowId);\n },\n isMaximized: async (windowId) => {\n console.log('[Preview Mock] windowControl.isMaximized:', windowId);\n return false;\n },\n };\n}\n\n/**\n * Mock Plugin Settings 实现(使用 localStorage 持久化)\n * @returns {Object}\n */\nexport function createMockPluginSettings() {\n return {\n get: async (pluginId) => {\n const key = `${STORAGE_PREFIX}${pluginId}`;\n try {\n const data = localStorage.getItem(key);\n return data ? JSON.parse(data) : {};\n } catch (e) {\n console.warn('[Preview Mock] getPluginSetting parse error:', e);\n return {};\n }\n },\n set: async (pluginId, settings) => {\n const key = `${STORAGE_PREFIX}${pluginId}`;\n try {\n localStorage.setItem(key, JSON.stringify(settings));\n console.log('[Preview Mock] setPluginSetting:', pluginId, settings);\n } catch (e) {\n console.warn('[Preview Mock] setPluginSetting error:', e);\n }\n },\n };\n}\n\n/**\n * Mock Logger 实现\n * @returns {Object}\n */\nexport function createMockLogger() {\n return {\n log: (...args) => console.log('[Preview]', ...args),\n info: (...args) => console.info('[Preview]', ...args),\n warn: (...args) => console.warn('[Preview]', ...args),\n error: (...args) => console.error('[Preview]', ...args),\n debug: (...args) => console.debug('[Preview]', ...args),\n };\n}\n\n/**\n * 创建完整的 mock electron 对象\n * @returns {Object}\n */\nexport function createMockElectron() {\n const mockIpc = createMockIpc();\n return {\n useIpc: () => mockIpc,\n dialog: createMockDialog(),\n shell: createMockShell(),\n clipboard: createMockClipboard(),\n openLink: async (url) => {\n console.log('[Preview Mock] openLink:', url);\n window.open(url, '_blank');\n },\n versions: {\n node: 'preview',\n chrome: navigator.userAgent.match(/Chrome\\/([0-9.]+)/)?.[1] || 'unknown',\n electron: 'preview',\n },\n APP_ROOT: '/preview',\n APPDATA_PATH: '/preview/appdata',\n };\n}\n\n/**\n * 创建完整的 mock ts 对象\n * @returns {Object}\n */\nexport function createMockTs() {\n const pluginSettings = createMockPluginSettings();\n return {\n getPluginSetting: pluginSettings.get,\n setPluginSetting: pluginSettings.set,\n windowControl: createMockWindowControl(),\n logger: createMockLogger(),\n net: {\n request: async (url, options) => {\n console.log('[Preview Mock] net.request:', url, options);\n try {\n const response = await fetch(url, options);\n return {\n ok: response.ok,\n status: response.status,\n data: await response.text(),\n };\n } catch (e) {\n return { ok: false, status: 0, error: e.message };\n }\n },\n },\n };\n}\n\n/**\n * 初始化 preview mock 环境\n * 将 mock 对象注入到 window\n */\nexport function initPreviewMock() {\n if (typeof window === 'undefined') {\n return;\n }\n\n // 只在未定义时注入,避免覆盖真实环境\n if (!window.electron) {\n window.electron = createMockElectron();\n console.log('[Preview Mock] window.electron injected');\n }\n\n if (!window.ts) {\n window.ts = createMockTs();\n console.log('[Preview Mock] window.ts injected');\n }\n}\n\n/**\n * 检查当前是否为 preview 模式\n * @returns {boolean}\n */\nexport function isPreviewMode() {\n // 通过 Vite define 注入的全局变量判断\n // eslint-disable-next-line no-undef\n if (typeof __TRANSLIME_PREVIEW__ !== 'undefined' && __TRANSLIME_PREVIEW__) {\n return true;\n }\n // 备用检测:检查是否在普通浏览器环境中运行\n if (typeof window !== 'undefined' && !window.electron && !window.ts) {\n return true;\n }\n return false;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
const STORAGE_PREFIX = "translime-preview-settings:";
|
|
2
|
+
function createMockIpc() {
|
|
3
|
+
return {
|
|
4
|
+
invoke: async (channel, ...args) => {
|
|
5
|
+
console.log("[Preview Mock] ipc.invoke:", channel, args);
|
|
6
|
+
return null;
|
|
7
|
+
},
|
|
8
|
+
send: (channel, ...args) => {
|
|
9
|
+
console.log("[Preview Mock] ipc.send:", channel, args);
|
|
10
|
+
},
|
|
11
|
+
on: (channel, callback) => {
|
|
12
|
+
console.log("[Preview Mock] ipc.on registered:", channel);
|
|
13
|
+
return () => {
|
|
14
|
+
console.log("[Preview Mock] ipc.on removed:", channel);
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
once: (channel, callback) => {
|
|
18
|
+
console.log("[Preview Mock] ipc.once registered:", channel);
|
|
19
|
+
},
|
|
20
|
+
removeListener: (channel, callback) => {
|
|
21
|
+
console.log("[Preview Mock] ipc.removeListener:", channel);
|
|
22
|
+
},
|
|
23
|
+
removeAllListeners: (channel) => {
|
|
24
|
+
console.log("[Preview Mock] ipc.removeAllListeners:", channel);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function createMockDialog() {
|
|
29
|
+
return {
|
|
30
|
+
showOpenDialog: async (options) => {
|
|
31
|
+
console.log("[Preview Mock] showOpenDialog:", options);
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
const input = document.createElement("input");
|
|
34
|
+
input.type = "file";
|
|
35
|
+
if (options?.properties?.includes("openDirectory")) {
|
|
36
|
+
input.webkitdirectory = true;
|
|
37
|
+
}
|
|
38
|
+
if (options?.properties?.includes("multiSelections")) {
|
|
39
|
+
input.multiple = true;
|
|
40
|
+
}
|
|
41
|
+
if (options?.filters) {
|
|
42
|
+
const accept = options.filters.flatMap((f) => f.extensions.map((ext) => `.${ext}`)).join(",");
|
|
43
|
+
input.accept = accept;
|
|
44
|
+
}
|
|
45
|
+
input.onchange = () => {
|
|
46
|
+
const filePaths = Array.from(input.files || []).map((f) => f.name);
|
|
47
|
+
resolve({ canceled: filePaths.length === 0, filePaths });
|
|
48
|
+
};
|
|
49
|
+
input.oncancel = () => {
|
|
50
|
+
resolve({ canceled: true, filePaths: [] });
|
|
51
|
+
};
|
|
52
|
+
input.click();
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
showSaveDialog: async (options) => {
|
|
56
|
+
console.log("[Preview Mock] showSaveDialog:", options);
|
|
57
|
+
const fileName = prompt("保存文件名:", options?.defaultPath || "file.txt");
|
|
58
|
+
return {
|
|
59
|
+
canceled: !fileName,
|
|
60
|
+
filePath: fileName || void 0
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
showMessageBox: async (options) => {
|
|
64
|
+
console.log("[Preview Mock] showMessageBox:", options);
|
|
65
|
+
const result = confirm(options?.message || "");
|
|
66
|
+
return { response: result ? 0 : 1 };
|
|
67
|
+
},
|
|
68
|
+
showErrorBox: (title, content) => {
|
|
69
|
+
console.error("[Preview Mock] showErrorBox:", title, content);
|
|
70
|
+
alert(`${title}
|
|
71
|
+
|
|
72
|
+
${content}`);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function createMockShell() {
|
|
77
|
+
return {
|
|
78
|
+
openExternal: async (url) => {
|
|
79
|
+
console.log("[Preview Mock] shell.openExternal:", url);
|
|
80
|
+
window.open(url, "_blank");
|
|
81
|
+
},
|
|
82
|
+
openPath: async (path) => {
|
|
83
|
+
console.log("[Preview Mock] shell.openPath:", path);
|
|
84
|
+
alert(`[Preview] 无法在浏览器中打开路径: ${path}`);
|
|
85
|
+
},
|
|
86
|
+
showItemInFolder: (path) => {
|
|
87
|
+
console.log("[Preview Mock] shell.showItemInFolder:", path);
|
|
88
|
+
alert(`[Preview] 无法在浏览器中显示文件夹: ${path}`);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function createMockClipboard() {
|
|
93
|
+
return {
|
|
94
|
+
readText: async () => {
|
|
95
|
+
try {
|
|
96
|
+
return await navigator.clipboard.readText();
|
|
97
|
+
} catch (e) {
|
|
98
|
+
console.warn("[Preview Mock] clipboard.readText failed:", e);
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
writeText: async (text) => {
|
|
103
|
+
try {
|
|
104
|
+
await navigator.clipboard.writeText(text);
|
|
105
|
+
console.log("[Preview Mock] clipboard.writeText:", text);
|
|
106
|
+
} catch (e) {
|
|
107
|
+
console.warn("[Preview Mock] clipboard.writeText failed:", e);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
readImage: async () => {
|
|
111
|
+
console.log("[Preview Mock] clipboard.readImage: not supported in preview");
|
|
112
|
+
return null;
|
|
113
|
+
},
|
|
114
|
+
writeImage: async () => {
|
|
115
|
+
console.log("[Preview Mock] clipboard.writeImage: not supported in preview");
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function createMockWindowControl() {
|
|
120
|
+
return {
|
|
121
|
+
close: (windowId) => {
|
|
122
|
+
console.log("[Preview Mock] windowControl.close:", windowId);
|
|
123
|
+
},
|
|
124
|
+
minimize: (windowId) => {
|
|
125
|
+
console.log("[Preview Mock] windowControl.minimize:", windowId);
|
|
126
|
+
},
|
|
127
|
+
maximize: (windowId) => {
|
|
128
|
+
console.log("[Preview Mock] windowControl.maximize:", windowId);
|
|
129
|
+
},
|
|
130
|
+
unmaximize: (windowId) => {
|
|
131
|
+
console.log("[Preview Mock] windowControl.unmaximize:", windowId);
|
|
132
|
+
},
|
|
133
|
+
devtools: (windowId) => {
|
|
134
|
+
console.log("[Preview Mock] windowControl.devtools:", windowId);
|
|
135
|
+
},
|
|
136
|
+
isMaximized: async (windowId) => {
|
|
137
|
+
console.log("[Preview Mock] windowControl.isMaximized:", windowId);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function createMockPluginSettings() {
|
|
143
|
+
return {
|
|
144
|
+
get: async (pluginId) => {
|
|
145
|
+
const key = `${STORAGE_PREFIX}${pluginId}`;
|
|
146
|
+
try {
|
|
147
|
+
const data = localStorage.getItem(key);
|
|
148
|
+
return data ? JSON.parse(data) : {};
|
|
149
|
+
} catch (e) {
|
|
150
|
+
console.warn("[Preview Mock] getPluginSetting parse error:", e);
|
|
151
|
+
return {};
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
set: async (pluginId, settings) => {
|
|
155
|
+
const key = `${STORAGE_PREFIX}${pluginId}`;
|
|
156
|
+
try {
|
|
157
|
+
localStorage.setItem(key, JSON.stringify(settings));
|
|
158
|
+
console.log("[Preview Mock] setPluginSetting:", pluginId, settings);
|
|
159
|
+
} catch (e) {
|
|
160
|
+
console.warn("[Preview Mock] setPluginSetting error:", e);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function createMockLogger() {
|
|
166
|
+
return {
|
|
167
|
+
log: (...args) => console.log("[Preview]", ...args),
|
|
168
|
+
info: (...args) => console.info("[Preview]", ...args),
|
|
169
|
+
warn: (...args) => console.warn("[Preview]", ...args),
|
|
170
|
+
error: (...args) => console.error("[Preview]", ...args),
|
|
171
|
+
debug: (...args) => console.debug("[Preview]", ...args)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function createMockElectron() {
|
|
175
|
+
const mockIpc = createMockIpc();
|
|
176
|
+
return {
|
|
177
|
+
useIpc: () => mockIpc,
|
|
178
|
+
dialog: createMockDialog(),
|
|
179
|
+
shell: createMockShell(),
|
|
180
|
+
clipboard: createMockClipboard(),
|
|
181
|
+
openLink: async (url) => {
|
|
182
|
+
console.log("[Preview Mock] openLink:", url);
|
|
183
|
+
window.open(url, "_blank");
|
|
184
|
+
},
|
|
185
|
+
versions: {
|
|
186
|
+
node: "preview",
|
|
187
|
+
chrome: navigator.userAgent.match(/Chrome\/([0-9.]+)/)?.[1] || "unknown",
|
|
188
|
+
electron: "preview"
|
|
189
|
+
},
|
|
190
|
+
APP_ROOT: "/preview",
|
|
191
|
+
APPDATA_PATH: "/preview/appdata"
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function createMockTs() {
|
|
195
|
+
const pluginSettings = createMockPluginSettings();
|
|
196
|
+
return {
|
|
197
|
+
getPluginSetting: pluginSettings.get,
|
|
198
|
+
setPluginSetting: pluginSettings.set,
|
|
199
|
+
windowControl: createMockWindowControl(),
|
|
200
|
+
logger: createMockLogger(),
|
|
201
|
+
net: {
|
|
202
|
+
request: async (url, options) => {
|
|
203
|
+
console.log("[Preview Mock] net.request:", url, options);
|
|
204
|
+
try {
|
|
205
|
+
const response = await fetch(url, options);
|
|
206
|
+
return {
|
|
207
|
+
ok: response.ok,
|
|
208
|
+
status: response.status,
|
|
209
|
+
data: await response.text()
|
|
210
|
+
};
|
|
211
|
+
} catch (e) {
|
|
212
|
+
return { ok: false, status: 0, error: e.message };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function initPreviewMock() {
|
|
219
|
+
if (typeof window === "undefined") {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (!window.electron) {
|
|
223
|
+
window.electron = createMockElectron();
|
|
224
|
+
console.log("[Preview Mock] window.electron injected");
|
|
225
|
+
}
|
|
226
|
+
if (!window.ts) {
|
|
227
|
+
window.ts = createMockTs();
|
|
228
|
+
console.log("[Preview Mock] window.ts injected");
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function isPreviewMode() {
|
|
232
|
+
if (typeof __TRANSLIME_PREVIEW__ !== "undefined" && __TRANSLIME_PREVIEW__) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
if (typeof window !== "undefined" && !window.electron && !window.ts) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
export {
|
|
241
|
+
createMockClipboard,
|
|
242
|
+
createMockDialog,
|
|
243
|
+
createMockElectron,
|
|
244
|
+
createMockIpc,
|
|
245
|
+
createMockLogger,
|
|
246
|
+
createMockPluginSettings,
|
|
247
|
+
createMockShell,
|
|
248
|
+
createMockTs,
|
|
249
|
+
createMockWindowControl,
|
|
250
|
+
initPreviewMock,
|
|
251
|
+
isPreviewMode
|
|
252
|
+
};
|
|
253
|
+
//# sourceMappingURL=preview-mock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-mock.js","sources":["../src/preview-mock.js"],"sourcesContent":["/**\n * Preview Mock 模块\n * 为 preview 模式提供 Electron API 的 mock 实现\n */\n\nconst STORAGE_PREFIX = 'translime-preview-settings:';\n\n/**\n * Mock IPC 实现\n * @returns {Object}\n */\nexport function createMockIpc() {\n return {\n invoke: async (channel, ...args) => {\n console.log('[Preview Mock] ipc.invoke:', channel, args);\n return null;\n },\n send: (channel, ...args) => {\n console.log('[Preview Mock] ipc.send:', channel, args);\n },\n on: (channel, callback) => {\n console.log('[Preview Mock] ipc.on registered:', channel);\n return () => {\n console.log('[Preview Mock] ipc.on removed:', channel);\n };\n },\n once: (channel, callback) => {\n console.log('[Preview Mock] ipc.once registered:', channel);\n },\n removeListener: (channel, callback) => {\n console.log('[Preview Mock] ipc.removeListener:', channel);\n },\n removeAllListeners: (channel) => {\n console.log('[Preview Mock] ipc.removeAllListeners:', channel);\n },\n };\n}\n\n/**\n * Mock Dialog 实现\n * @returns {Object}\n */\nexport function createMockDialog() {\n return {\n showOpenDialog: async (options) => {\n console.log('[Preview Mock] showOpenDialog:', options);\n // 在 preview 模式下,使用原生 file input 模拟\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n if (options?.properties?.includes('openDirectory')) {\n input.webkitdirectory = true;\n }\n if (options?.properties?.includes('multiSelections')) {\n input.multiple = true;\n }\n if (options?.filters) {\n const accept = options.filters\n .flatMap((f) => f.extensions.map((ext) => `.${ext}`))\n .join(',');\n input.accept = accept;\n }\n input.onchange = () => {\n const filePaths = Array.from(input.files || []).map((f) => f.name);\n resolve({ canceled: filePaths.length === 0, filePaths });\n };\n input.oncancel = () => {\n resolve({ canceled: true, filePaths: [] });\n };\n input.click();\n });\n },\n showSaveDialog: async (options) => {\n console.log('[Preview Mock] showSaveDialog:', options);\n const fileName = prompt('保存文件名:', options?.defaultPath || 'file.txt');\n return {\n canceled: !fileName,\n filePath: fileName || undefined,\n };\n },\n showMessageBox: async (options) => {\n console.log('[Preview Mock] showMessageBox:', options);\n const result = confirm(options?.message || '');\n return { response: result ? 0 : 1 };\n },\n showErrorBox: (title, content) => {\n console.error('[Preview Mock] showErrorBox:', title, content);\n alert(`${title}\\n\\n${content}`);\n },\n };\n}\n\n/**\n * Mock Shell 实现\n * @returns {Object}\n */\nexport function createMockShell() {\n return {\n openExternal: async (url) => {\n console.log('[Preview Mock] shell.openExternal:', url);\n window.open(url, '_blank');\n },\n openPath: async (path) => {\n console.log('[Preview Mock] shell.openPath:', path);\n alert(`[Preview] 无法在浏览器中打开路径: ${path}`);\n },\n showItemInFolder: (path) => {\n console.log('[Preview Mock] shell.showItemInFolder:', path);\n alert(`[Preview] 无法在浏览器中显示文件夹: ${path}`);\n },\n };\n}\n\n/**\n * Mock Clipboard 实现\n * @returns {Object}\n */\nexport function createMockClipboard() {\n return {\n readText: async () => {\n try {\n return await navigator.clipboard.readText();\n } catch (e) {\n console.warn('[Preview Mock] clipboard.readText failed:', e);\n return '';\n }\n },\n writeText: async (text) => {\n try {\n await navigator.clipboard.writeText(text);\n console.log('[Preview Mock] clipboard.writeText:', text);\n } catch (e) {\n console.warn('[Preview Mock] clipboard.writeText failed:', e);\n }\n },\n readImage: async () => {\n console.log('[Preview Mock] clipboard.readImage: not supported in preview');\n return null;\n },\n writeImage: async () => {\n console.log('[Preview Mock] clipboard.writeImage: not supported in preview');\n },\n };\n}\n\n/**\n * Mock Window Control 实现\n * @returns {Object}\n */\nexport function createMockWindowControl() {\n return {\n close: (windowId) => {\n console.log('[Preview Mock] windowControl.close:', windowId);\n },\n minimize: (windowId) => {\n console.log('[Preview Mock] windowControl.minimize:', windowId);\n },\n maximize: (windowId) => {\n console.log('[Preview Mock] windowControl.maximize:', windowId);\n },\n unmaximize: (windowId) => {\n console.log('[Preview Mock] windowControl.unmaximize:', windowId);\n },\n devtools: (windowId) => {\n console.log('[Preview Mock] windowControl.devtools:', windowId);\n },\n isMaximized: async (windowId) => {\n console.log('[Preview Mock] windowControl.isMaximized:', windowId);\n return false;\n },\n };\n}\n\n/**\n * Mock Plugin Settings 实现(使用 localStorage 持久化)\n * @returns {Object}\n */\nexport function createMockPluginSettings() {\n return {\n get: async (pluginId) => {\n const key = `${STORAGE_PREFIX}${pluginId}`;\n try {\n const data = localStorage.getItem(key);\n return data ? JSON.parse(data) : {};\n } catch (e) {\n console.warn('[Preview Mock] getPluginSetting parse error:', e);\n return {};\n }\n },\n set: async (pluginId, settings) => {\n const key = `${STORAGE_PREFIX}${pluginId}`;\n try {\n localStorage.setItem(key, JSON.stringify(settings));\n console.log('[Preview Mock] setPluginSetting:', pluginId, settings);\n } catch (e) {\n console.warn('[Preview Mock] setPluginSetting error:', e);\n }\n },\n };\n}\n\n/**\n * Mock Logger 实现\n * @returns {Object}\n */\nexport function createMockLogger() {\n return {\n log: (...args) => console.log('[Preview]', ...args),\n info: (...args) => console.info('[Preview]', ...args),\n warn: (...args) => console.warn('[Preview]', ...args),\n error: (...args) => console.error('[Preview]', ...args),\n debug: (...args) => console.debug('[Preview]', ...args),\n };\n}\n\n/**\n * 创建完整的 mock electron 对象\n * @returns {Object}\n */\nexport function createMockElectron() {\n const mockIpc = createMockIpc();\n return {\n useIpc: () => mockIpc,\n dialog: createMockDialog(),\n shell: createMockShell(),\n clipboard: createMockClipboard(),\n openLink: async (url) => {\n console.log('[Preview Mock] openLink:', url);\n window.open(url, '_blank');\n },\n versions: {\n node: 'preview',\n chrome: navigator.userAgent.match(/Chrome\\/([0-9.]+)/)?.[1] || 'unknown',\n electron: 'preview',\n },\n APP_ROOT: '/preview',\n APPDATA_PATH: '/preview/appdata',\n };\n}\n\n/**\n * 创建完整的 mock ts 对象\n * @returns {Object}\n */\nexport function createMockTs() {\n const pluginSettings = createMockPluginSettings();\n return {\n getPluginSetting: pluginSettings.get,\n setPluginSetting: pluginSettings.set,\n windowControl: createMockWindowControl(),\n logger: createMockLogger(),\n net: {\n request: async (url, options) => {\n console.log('[Preview Mock] net.request:', url, options);\n try {\n const response = await fetch(url, options);\n return {\n ok: response.ok,\n status: response.status,\n data: await response.text(),\n };\n } catch (e) {\n return { ok: false, status: 0, error: e.message };\n }\n },\n },\n };\n}\n\n/**\n * 初始化 preview mock 环境\n * 将 mock 对象注入到 window\n */\nexport function initPreviewMock() {\n if (typeof window === 'undefined') {\n return;\n }\n\n // 只在未定义时注入,避免覆盖真实环境\n if (!window.electron) {\n window.electron = createMockElectron();\n console.log('[Preview Mock] window.electron injected');\n }\n\n if (!window.ts) {\n window.ts = createMockTs();\n console.log('[Preview Mock] window.ts injected');\n }\n}\n\n/**\n * 检查当前是否为 preview 模式\n * @returns {boolean}\n */\nexport function isPreviewMode() {\n // 通过 Vite define 注入的全局变量判断\n // eslint-disable-next-line no-undef\n if (typeof __TRANSLIME_PREVIEW__ !== 'undefined' && __TRANSLIME_PREVIEW__) {\n return true;\n }\n // 备用检测:检查是否在普通浏览器环境中运行\n if (typeof window !== 'undefined' && !window.electron && !window.ts) {\n return true;\n }\n return false;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Plugin Preview</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/__PREVIEW_ENTRY__"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|