4 | {{ lang("dialog_panel_outdate_content1")}} 5 |
6 |12 | {{ lang("dialog_panel_outdate_content2")}} 13 |
14 |%%PATH%%,它将被替换为图片实际路径。",
24 |
25 | "local_editor_frontend_error": "当前前端环境不支持本地编辑器调用,仅支持桌面版客户端",
26 | "local_editor_backend_error": "当前后端环境不支持本地编辑器调用",
27 |
28 | "setting_about_name": "关于",
29 | "setting_about_desp": "作者:OpaqueGlass;%%PATH%%, and it will be replaced with the actual image path.",
75 | "setting_localEditorWaitingDialog_name": "Enable Waiting Dialog",
76 | "setting_localEditorWaitingDialog_desp": "Show a waiting dialog when the local editor is called.",
77 | "settingpage_none_name": "No Column"
78 | }
--------------------------------------------------------------------------------
/src/editor/localEditor.ts:
--------------------------------------------------------------------------------
1 | import { errorPush, logPush } from "@/logger";
2 | import { getReadOnlyGSettings } from "@/manager/settingManager";
3 | import { escapeHTML, showPluginMessage } from "@/utils/common";
4 | import { isValidStr } from "@/utils/commonCheck";
5 | import { Dialog, getBackend, getFrontend, Protyle } from "siyuan";
6 | import BaseImageEditor from "./baseImageEditor";
7 | import { lang } from "@/utils/lang";
8 | import { refreshImg } from "@/manager/editorHelper";
9 |
10 | export class LocalCmdEditor extends BaseImageEditor {
11 | public async init() {
12 |
13 | }
14 |
15 | public async showImageEditor({ source, filePath, element, protyle }: { source: string; filePath: string, element: HTMLElement, protyle: Protyle }) {
16 | const { spawn } = window.require("child_process");
17 | const path = window.require("path");
18 | // 本地路径需要去除参数
19 | let src = element.getAttribute('src') || '';
20 | let base = src.split('?')[0];
21 | logPush("打开本地编辑器", path.join(window.siyuan.config.system.dataDir, base));
22 |
23 | const g_setting = getReadOnlyGSettings();
24 | if (!isValidStr(g_setting.localEditorPath)) {
25 | showPluginMessage(lang("msg_not_set_exec_path"));
26 | return;
27 | }
28 | const args = g_setting.localEditorArgs ? g_setting.localEditorArgs.split('\n') : [];
29 | const imagePath = path.join(window.siyuan.config.system.dataDir, base);
30 | // 如果为空,则补充 path, 如果不为空,替换其中的%%PATH%%为path
31 | const finalArgs = args.length > 0 ? args.map((v: string) => {
32 | if (v.indexOf('%%PATH%%') >= 0) {
33 | return v.replace(/%%PATH%%/g, imagePath);
34 | }
35 | return v;
36 | }) : [imagePath];
37 | logPush("编辑器调用参数", g_setting.localEditorPath, finalArgs);
38 | const child = spawn(g_setting.localEditorPath, finalArgs);
39 | showPluginMessage(lang("msg_called_external_editor"));
40 | child.on("error", (err) => {
41 | showPluginMessage(lang("msg_call_external_editor_failed") + err.message, 8000, "error");
42 | errorPush("本地编辑器调用失败", err);
43 | });
44 | child.stdout.on("data", (data) => {
45 | logPush(`stdout: ${data}`);
46 | });
47 |
48 | child.stderr.on("data", (data) => {
49 | logPush(`stderr: ${data}`);
50 | });
51 | const callDate = new Date();
52 | child.on("close", (code) => {
53 | logPush(`子进程退出,code = ${code}`);
54 | const endDate = new Date();
55 | if (endDate.getTime() - callDate.getTime() < 3000) {
56 | const dialogContent = `
57 |