translime-sdk 1.0.1 → 1.0.3

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