diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ad7f54f..7cbcf53 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -37,5 +37,5 @@ jobs: - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.GH_TOKEN }} publish_dir: docs/dist \ No newline at end of file diff --git a/README.md b/README.md index d3448ec..41dfee1 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发 - **C++** - **Go** - **Groovy** +- **HTML** - **Java** - **JavaScript (Browser)** - **JavaScript (jQuery)** @@ -51,6 +52,7 @@ CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发 - Node.js 18+ - Rust 1.8+ - Tauri 2.x +- Vue 3.x **构建步骤:** diff --git a/package.json b/package.json index 7bfd450..45d7ca0 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@babel/runtime": "^7.28.2", "@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-go": "^6.0.1", + "@codemirror/lang-html": "^6.4.9", "@codemirror/lang-java": "^6.0.2", "@codemirror/lang-javascript": "^6.2.4", "@codemirror/lang-python": "^6.2.1", @@ -23,6 +24,7 @@ "@codemirror/view": "^6.38.1", "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "^2.3.2", + "@tauri-apps/plugin-fs": "^2.4.2", "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-shell": "^2.3.0", "@uiw/codemirror-themes-all": "^4.24.2", diff --git a/public/icons/html.svg b/public/icons/html.svg new file mode 100644 index 0000000..282ac4f --- /dev/null +++ b/public/icons/html.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 993e9e4..40e5a09 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -19,6 +19,7 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-dialog", + "tauri-plugin-fs", "tauri-plugin-opener", "tauri-plugin-shell", "tempfile", @@ -851,9 +852,9 @@ dependencies = [ [[package]] name = "dlopen2" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +checksum = "b54f373ccf864bf587a89e880fb7610f8d73f3045f13580948ccbcaff26febff" dependencies = [ "dlopen2_derive", "libc", @@ -2509,6 +2510,16 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc2-javascript-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9052cb1bb50a4c161d934befcf879526fb87ae9a68858f241e693ca46225cf5a" +dependencies = [ + "objc2 0.6.1", + "objc2-core-foundation", +] + [[package]] name = "objc2-metal" version = "0.2.2" @@ -2545,6 +2556,17 @@ dependencies = [ "objc2-foundation 0.3.1", ] +[[package]] +name = "objc2-security" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1f8e0ef3ab66b08c42644dcb34dba6ec0a574bbd8adbb8bdbdc7a2779731a44" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", +] + [[package]] name = "objc2-ui-kit" version = "0.3.1" @@ -2569,6 +2591,8 @@ dependencies = [ "objc2-app-kit", "objc2-core-foundation", "objc2-foundation 0.3.1", + "objc2-javascript-core", + "objc2-security", ] [[package]] @@ -3671,9 +3695,9 @@ dependencies = [ [[package]] name = "serialize-to-javascript" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" dependencies = [ "serde", "serde_json", @@ -3682,13 +3706,13 @@ dependencies = [ [[package]] name = "serialize-to-javascript-impl" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.104", ] [[package]] @@ -3995,11 +4019,12 @@ dependencies = [ [[package]] name = "tao" -version = "0.34.0" +version = "0.34.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c380ca75a231b87b6c9dd86948f035012e7171d1a7c40a9c2890489a7ffd8a" +checksum = "4daa814018fecdfb977b59a094df4bd43b42e8e21f88fddfc05807e6f46efaaf" dependencies = [ "bitflags 2.9.1", + "block2 0.6.1", "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", @@ -4051,12 +4076,13 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.7.0" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352a4bc7bf6c25f5624227e3641adf475a6535707451b09bb83271df8b7a6ac7" +checksum = "5d545ccf7b60dcd44e07c6fb5aeb09140966f0aabd5d2aa14a6821df7bc99348" dependencies = [ "anyhow", "bytes", + "cookie", "dirs", "dunce", "embed_plist", @@ -4074,6 +4100,7 @@ dependencies = [ "objc2-app-kit", "objc2-foundation 0.3.1", "objc2-ui-kit", + "objc2-web-kit", "percent-encoding", "plist", "raw-window-handle", @@ -4101,9 +4128,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "182d688496c06bf08ea896459bf483eb29cdff35c1c4c115fb14053514303064" +checksum = "67945dbaf8920dbe3a1e56721a419a0c3d085254ab24cff5b9ad55e2b0016e0b" dependencies = [ "anyhow", "cargo_toml", @@ -4117,15 +4144,15 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml 0.8.23", + "toml 0.9.5", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b54a99a6cd8e01abcfa61508177e6096a4fe2681efecee9214e962f2f073ae4a" +checksum = "1ab3a62cf2e6253936a8b267c2e95839674e7439f104fa96ad0025e149d54d8a" dependencies = [ "base64 0.22.1", "brotli", @@ -4150,9 +4177,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.3.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7945b14dc45e23532f2ded6e120170bbdd4af5ceaa45784a6b33d250fbce3f9e" +checksum = "4368ea8094e7045217edb690f493b55b30caf9f3e61f79b4c24b6db91f07995e" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4164,9 +4191,9 @@ dependencies = [ [[package]] name = "tauri-plugin" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd5c1e56990c70a906ef67a9851bbdba9136d26075ee9a2b19c8b46986b3e02" +checksum = "9946a3cede302eac0c6eb6c6070ac47b1768e326092d32efbb91f21ed58d978f" dependencies = [ "anyhow", "glob", @@ -4175,7 +4202,7 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "toml 0.8.23", + "toml 0.9.5", "walkdir", ] @@ -4199,9 +4226,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6ef84ee2f2094ce093e55106d90d763ba343fad57566992962e8f76d113f99" +checksum = "315784ec4be45e90a987687bae7235e6be3d6e9e350d2b75c16b8a4bf22c1db7" dependencies = [ "anyhow", "dunce", @@ -4215,7 +4242,7 @@ dependencies = [ "tauri-plugin", "tauri-utils", "thiserror 2.0.12", - "toml 0.8.23", + "toml 0.9.5", "url", ] @@ -4264,9 +4291,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b1cc885be806ea15ff7b0eb47098a7b16323d9228876afda329e34e2d6c4676" +checksum = "d4cfc9ad45b487d3fded5a4731a567872a4812e9552e3964161b08edabf93846" dependencies = [ "cookie", "dpi", @@ -4275,20 +4302,23 @@ dependencies = [ "jni", "objc2 0.6.1", "objc2-ui-kit", + "objc2-web-kit", "raw-window-handle", "serde", "serde_json", "tauri-utils", "thiserror 2.0.12", "url", + "webkit2gtk", + "webview2-com", "windows", ] [[package]] name = "tauri-runtime-wry" -version = "2.7.2" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe653a2fbbef19fe898efc774bc52c8742576342a33d3d028c189b57eb1d2439" +checksum = "c1fe9d48bd122ff002064e88cfcd7027090d789c4302714e68fcccba0f4b7807" dependencies = [ "gtk", "http 1.3.1", @@ -4313,9 +4343,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330c15cabfe1d9f213478c9e8ec2b0c76dab26bb6f314b8ad1c8a568c1d186e" +checksum = "41a3852fdf9a4f8fbeaa63dc3e9a85284dd6ef7200751f0bd66ceee30c93f212" dependencies = [ "anyhow", "brotli", @@ -4342,7 +4372,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror 2.0.12", - "toml 0.8.23", + "toml 0.9.5", "url", "urlpattern", "uuid", @@ -4583,7 +4613,6 @@ dependencies = [ "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", - "toml_write", "winnow 0.7.12", ] @@ -4596,12 +4625,6 @@ dependencies = [ "winnow 0.7.12", ] -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - [[package]] name = "toml_writer" version = "1.0.2" @@ -5663,14 +5686,15 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "wry" -version = "0.52.1" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a714d9ba7075aae04a6e50229d6109e3d584774b99a6a8c60de1698ca111b9" +checksum = "e3b6763512fe4b51c80b3ce9b50939d682acb4de335dfabbdb20d7a2642199b7" dependencies = [ "base64 0.22.1", "block2 0.6.1", "cookie", "crossbeam-channel", + "dirs", "dpi", "dunce", "gdkx11", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cab5fce..aa9bd53 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -14,10 +14,11 @@ tauri-build = { version = "2", features = [] } chrono = { version = "0.4.41", features = ["serde"] } [dependencies] -tauri = { version = "2", features = ["devtools"] } +tauri = { version = "2", features = [ "devtools"] } tauri-plugin-opener = "2" tauri-plugin-shell = "2.0" tauri-plugin-dialog = "2.0" +tauri-plugin-fs = "2.4.2" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = "1.47.1" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 19d0cce..142800c 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -18,6 +18,24 @@ }, "shell:default", "shell:allow-open", - "dialog:default" + "dialog:default", + "fs:allow-read-text-file", + { + "identifier": "fs:scope", + "allow": [ + { + "path": "/var/folders/**" + }, + { + "path": "/tmp/**" + }, + { + "path": "/private/var/folders/**" + }, + { + "path": "**" + } + ] + } ] -} +} \ No newline at end of file diff --git a/src-tauri/src/examples/html.html b/src-tauri/src/examples/html.html new file mode 100644 index 0000000..ddaf4f7 --- /dev/null +++ b/src-tauri/src/examples/html.html @@ -0,0 +1,293 @@ + + + + + + CodeForge HTML 代码示例 + + + +
+ +
+

🎉 欢迎使用 CodeForge!

+

Welcome to CodeForge!

+
+

CodeForge HTML

+
+ + +
+

✅ 基本输出 (Basic Output)

+
+
✅ HTML 运行成功! (HTML is working!)
+
🌐 这是 HTML 程序 (This is HTML program)
+
+
+ + +
+

🔢 简单计算 (Simple Calculation)

+
+ +
+
点击按钮执行计算...
+
+ + +
+

📝 字符串操作 (String Operations)

+
+
平台名称 (Platform): CodeForge
+
语言版本 (Language): HTML
+
完整信息 (Full info): CodeForge - HTML
+
+
+ + +
+

🔄 循环输出 (Loop Output)

+
+ +
+
点击按钮显示循环输出...
+
+ + +
+

🍎 水果列表 (Fruit List)

+ +
+ + +
+

📊 成绩评估 (Score Evaluation)

+
+ + +
+
+ 当前成绩: 85 分 - 良好! (Good!) +
+
+ + +
+

🔍 DOM操作示例 (DOM Manipulation Example)

+
+ +
+
点击按钮查看DOM操作...
+
+ + +
+

🎭 函数示例 (Function Example)

+
+ + +
+
输入姓名后点击按钮...
+
+ + +
+

🎯 CodeForge HTML 代码执行完成!

+

🎯 CodeForge HTML execution completed!

+

感谢使用 CodeForge 代码执行环境! 🚀

+

Thank you for using CodeForge! 🚀

+
+
+ + + + \ No newline at end of file diff --git a/src-tauri/src/examples/ruby.rb b/src-tauri/src/examples/ruby.rb index 9be4776..6214528 100644 --- a/src-tauri/src/examples/ruby.rb +++ b/src-tauri/src/examples/ruby.rb @@ -288,4 +288,4 @@ class DynamicClass puts "🎯 CodeForge Ruby execution completed!" puts "" puts "感谢使用 CodeForge 代码执行环境! 🚀" -puts "Thank you for using CodeForge! \ No newline at end of file +puts "Thank you for using CodeForge!" \ No newline at end of file diff --git a/src-tauri/src/execution.rs b/src-tauri/src/execution.rs index 726ca9d..f0e38b5 100644 --- a/src-tauri/src/execution.rs +++ b/src-tauri/src/execution.rs @@ -136,7 +136,7 @@ pub async fn execute_code( .unwrap() .as_secs(); - let _ = fs::remove_file(&file_path); + // let _ = fs::remove_file(&file_path); let _ = app.emit( "code-execution-complete", serde_json::json!({ @@ -212,7 +212,7 @@ pub async fn execute_code( ); let _ = child.kill(); let _ = child.wait(); - let _ = fs::remove_file(&file_path); + // let _ = fs::remove_file(&file_path); // 从任务管理器中移除 { @@ -235,7 +235,7 @@ pub async fn execute_code( if start_time.elapsed() > timeout { let _ = child.kill(); let _ = child.wait(); - let _ = fs::remove_file(&file_path); + // let _ = fs::remove_file(&file_path); // 从任务管理器中移除 { @@ -317,7 +317,7 @@ pub async fn execute_code( .unwrap() .as_secs(); - let _ = fs::remove_file(&file_path); + // let _ = fs::remove_file(&file_path); // 从任务管理器中移除 { @@ -376,7 +376,7 @@ pub async fn execute_code( Err(e) => { let _ = child.kill(); let _ = child.wait(); - let _ = fs::remove_file(&file_path); + // let _ = fs::remove_file(&file_path); // 从任务管理器中移除 { diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 10bfbe5..2ce1fca 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -35,6 +35,7 @@ fn main() { .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_fs::init()) .manage(ExecutionHistory::default()) .manage(ExecutionPluginManagerState::new(PluginManager::new())) .setup(|app| { diff --git a/src-tauri/src/plugins/applescript.rs b/src-tauri/src/plugins/applescript.rs index 7701d1c..4c4cf68 100644 --- a/src-tauri/src/plugins/applescript.rs +++ b/src-tauri/src/plugins/applescript.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for AppleScriptPlugin { after_compile: None, template: Some(String::from("-- 在这里输入 AppleScript 代码")), timeout: Some(45), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/c.rs b/src-tauri/src/plugins/c.rs index 1951127..515a567 100644 --- a/src-tauri/src/plugins/c.rs +++ b/src-tauri/src/plugins/c.rs @@ -66,6 +66,7 @@ impl LanguagePlugin for CPlugin { after_compile: Some(String::from("rm -f $filename")), template: Some(String::from("// 在这里输入 C 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/clojure.rs b/src-tauri/src/plugins/clojure.rs index 050fd28..402b89f 100644 --- a/src-tauri/src/plugins/clojure.rs +++ b/src-tauri/src/plugins/clojure.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for ClojurePlugin { after_compile: None, template: Some(String::from(";; 在这里输入 Clojure 代码")), timeout: Some(45), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/cpp.rs b/src-tauri/src/plugins/cpp.rs index a2abff6..e102f11 100644 --- a/src-tauri/src/plugins/cpp.rs +++ b/src-tauri/src/plugins/cpp.rs @@ -66,6 +66,7 @@ impl LanguagePlugin for CppPlugin { after_compile: Some(String::from("rm -f $filename")), template: Some(String::from("// 在这里输入 C++ 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/go.rs b/src-tauri/src/plugins/go.rs index 6e06b16..1f9b935 100644 --- a/src-tauri/src/plugins/go.rs +++ b/src-tauri/src/plugins/go.rs @@ -35,6 +35,7 @@ impl LanguagePlugin for GoPlugin { after_compile: None, template: Some(String::from("// 在这里输入 Go 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/groovy.rs b/src-tauri/src/plugins/groovy.rs index 9da9651..6715e56 100644 --- a/src-tauri/src/plugins/groovy.rs +++ b/src-tauri/src/plugins/groovy.rs @@ -76,6 +76,7 @@ impl LanguagePlugin for GroovyPlugin { after_compile: None, template: Some(String::from("// 在这里输入 Groovy 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/html.rs b/src-tauri/src/plugins/html.rs new file mode 100644 index 0000000..aaae68e --- /dev/null +++ b/src-tauri/src/plugins/html.rs @@ -0,0 +1,53 @@ +use super::{LanguagePlugin, PluginConfig}; +use std::vec; + +pub struct HtmlPlugin; + +impl LanguagePlugin for HtmlPlugin { + fn get_order(&self) -> i32 { + 20 + } + + fn get_language_name(&self) -> &'static str { + "HTML" + } + + fn get_language_key(&self) -> &'static str { + "html" + } + + fn get_file_extension(&self) -> String { + self.get_config() + .map(|config| config.extension.clone()) + .unwrap_or_else(|| "html".to_string()) + } + + fn get_version_args(&self) -> Vec<&'static str> { + vec!["--"] + } + + fn get_path_command(&self) -> String { + "--".to_string() + } + + fn get_default_config(&self) -> PluginConfig { + PluginConfig { + enabled: true, + language: String::from("html"), + before_compile: None, + extension: String::from("html"), + execute_home: None, + run_command: Some(String::from("cat $filename")), + after_compile: None, + template: Some(String::from("// 在这里输入 HTML 代码")), + timeout: Some(30), + console_type: Some(String::from("web")), + } + } + + fn get_default_command(&self) -> String { + self.get_config() + .and_then(|config| config.run_command.clone()) + .unwrap_or_else(|| "--".to_string()) + } +} diff --git a/src-tauri/src/plugins/java.rs b/src-tauri/src/plugins/java.rs index 80bea43..2291652 100644 --- a/src-tauri/src/plugins/java.rs +++ b/src-tauri/src/plugins/java.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for JavaPlugin { after_compile: Some(String::from("rm -f *.class")), template: Some(String::from("// 在这里输入 Java 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/javascript_browser.rs b/src-tauri/src/plugins/javascript_browser.rs index f88cf96..79c0eb3 100644 --- a/src-tauri/src/plugins/javascript_browser.rs +++ b/src-tauri/src/plugins/javascript_browser.rs @@ -43,6 +43,7 @@ impl LanguagePlugin for JavaScriptBrowserPlugin { after_compile: None, template: Some(String::from("// 在这里输入 JavaScript (Browser) 代码")), timeout: Some(30), + console_type: Some(String::from("web")), } } diff --git a/src-tauri/src/plugins/javascript_jquery.rs b/src-tauri/src/plugins/javascript_jquery.rs index 4922df9..952f690 100644 --- a/src-tauri/src/plugins/javascript_jquery.rs +++ b/src-tauri/src/plugins/javascript_jquery.rs @@ -43,6 +43,7 @@ impl LanguagePlugin for JavaScriptJQueryPlugin { after_compile: None, template: Some(String::from("// 在这里输入 JavaScript (jQuery) 代码")), timeout: Some(30), + console_type: Some(String::from("web")), } } diff --git a/src-tauri/src/plugins/javascript_nodejs.rs b/src-tauri/src/plugins/javascript_nodejs.rs index 8f398fb..8218f91 100644 --- a/src-tauri/src/plugins/javascript_nodejs.rs +++ b/src-tauri/src/plugins/javascript_nodejs.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for JavaScriptNodeJsPlugin { after_compile: None, template: Some(String::from("// 在这里输入 JavaScript (Node.js) 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/kotlin.rs b/src-tauri/src/plugins/kotlin.rs index ea7a883..be69898 100644 --- a/src-tauri/src/plugins/kotlin.rs +++ b/src-tauri/src/plugins/kotlin.rs @@ -68,6 +68,7 @@ impl LanguagePlugin for KotlinPlugin { after_compile: Some(String::from("rm -f *.class")), template: Some(String::from("// 在这里输入 Kotlin 代码")), timeout: Some(60), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/manager.rs b/src-tauri/src/plugins/manager.rs index 3920833..3398a59 100644 --- a/src-tauri/src/plugins/manager.rs +++ b/src-tauri/src/plugins/manager.rs @@ -5,6 +5,7 @@ use crate::plugins::clojure::ClojurePlugin; use crate::plugins::cpp::CppPlugin; use crate::plugins::go::GoPlugin; use crate::plugins::groovy::GroovyPlugin; +use crate::plugins::html::HtmlPlugin; use crate::plugins::java::JavaPlugin; use crate::plugins::javascript_browser::JavaScriptBrowserPlugin; use crate::plugins::javascript_jquery::JavaScriptJQueryPlugin; @@ -48,6 +49,7 @@ impl PluginManager { plugins.insert("typescript".to_string(), Box::new(TypeScriptPlugin)); plugins.insert("cpp".to_string(), Box::new(CppPlugin)); plugins.insert("groovy".to_string(), Box::new(GroovyPlugin)); + plugins.insert("html".to_string(), Box::new(HtmlPlugin)); plugins.insert( "javascript-nodejs".to_string(), Box::new(JavaScriptNodeJsPlugin), diff --git a/src-tauri/src/plugins/mod.rs b/src-tauri/src/plugins/mod.rs index 528468a..a700e5e 100644 --- a/src-tauri/src/plugins/mod.rs +++ b/src-tauri/src/plugins/mod.rs @@ -41,6 +41,7 @@ pub struct PluginConfig { pub run_command: Option, // 插件执行的命令,例如 "python2 $filename" pub template: Option, // 插件的模板 pub timeout: Option, // 插件的超时时间 + pub console_type: Option, // 插件的输出类型 } // 语言插件接口 @@ -374,6 +375,7 @@ pub mod clojure; pub mod cpp; pub mod go; pub mod groovy; +pub mod html; pub mod java; pub mod javascript_browser; pub mod javascript_jquery; diff --git a/src-tauri/src/plugins/nodejs.rs b/src-tauri/src/plugins/nodejs.rs index 4ead9d2..58d8cb4 100644 --- a/src-tauri/src/plugins/nodejs.rs +++ b/src-tauri/src/plugins/nodejs.rs @@ -40,6 +40,7 @@ impl LanguagePlugin for NodeJSPlugin { after_compile: None, template: Some(String::from("// 在这里输入 Node.js 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/python2.rs b/src-tauri/src/plugins/python2.rs index 2c31218..95a5957 100644 --- a/src-tauri/src/plugins/python2.rs +++ b/src-tauri/src/plugins/python2.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for Python2Plugin { after_compile: None, template: Some(String::from("# 在这里输入 Python 2 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/python3.rs b/src-tauri/src/plugins/python3.rs index 95dd815..5ee737a 100644 --- a/src-tauri/src/plugins/python3.rs +++ b/src-tauri/src/plugins/python3.rs @@ -40,6 +40,7 @@ impl LanguagePlugin for Python3Plugin { after_compile: None, template: Some(String::from("# 在这里输入 Python 3 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/ruby.rs b/src-tauri/src/plugins/ruby.rs index 4e5c87a..34a30ab 100644 --- a/src-tauri/src/plugins/ruby.rs +++ b/src-tauri/src/plugins/ruby.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for RubyPlugin { after_compile: None, template: Some(String::from("# 在这里输入 Ruby 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/rust.rs b/src-tauri/src/plugins/rust.rs index 6691120..3898a93 100644 --- a/src-tauri/src/plugins/rust.rs +++ b/src-tauri/src/plugins/rust.rs @@ -54,6 +54,7 @@ impl LanguagePlugin for RustPlugin { after_compile: Some(String::from("rm -f /tmp/main")), template: Some(String::from("# 在这里输入 Rust 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/scala.rs b/src-tauri/src/plugins/scala.rs index 63c1472..7ed1b4d 100644 --- a/src-tauri/src/plugins/scala.rs +++ b/src-tauri/src/plugins/scala.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for ScalaPlugin { after_compile: Some(String::from("rm -f *.class")), template: Some(String::from("// 在这里输入 Scala 代码")), timeout: Some(45), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/shell.rs b/src-tauri/src/plugins/shell.rs index e5177b8..9f62d81 100644 --- a/src-tauri/src/plugins/shell.rs +++ b/src-tauri/src/plugins/shell.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for ShellPlugin { after_compile: None, template: Some(String::from("# 在这里输入 Shell 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/swift.rs b/src-tauri/src/plugins/swift.rs index 03cb8b6..82e0993 100644 --- a/src-tauri/src/plugins/swift.rs +++ b/src-tauri/src/plugins/swift.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for SwiftPlugin { after_compile: None, template: Some(String::from("// 在这里输入 Swift 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/typescript.rs b/src-tauri/src/plugins/typescript.rs index f7a51fe..afb33e1 100644 --- a/src-tauri/src/plugins/typescript.rs +++ b/src-tauri/src/plugins/typescript.rs @@ -68,6 +68,7 @@ impl LanguagePlugin for TypeScriptPlugin { after_compile: Some(String::from("rm -f *.js")), template: Some(String::from("// 在这里输入 TypeScript 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/typescript_browser.rs b/src-tauri/src/plugins/typescript_browser.rs index 5e1b12b..43ea4d9 100644 --- a/src-tauri/src/plugins/typescript_browser.rs +++ b/src-tauri/src/plugins/typescript_browser.rs @@ -70,6 +70,7 @@ impl LanguagePlugin for TypeScriptBrowserPlugin { after_compile: Some(String::from("rm -f *.js")), template: Some(String::from("// 在这里输入 TypeScript (Browser) 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src-tauri/src/plugins/typescript_nodejs.rs b/src-tauri/src/plugins/typescript_nodejs.rs index b88cd51..1dc773a 100644 --- a/src-tauri/src/plugins/typescript_nodejs.rs +++ b/src-tauri/src/plugins/typescript_nodejs.rs @@ -41,6 +41,7 @@ impl LanguagePlugin for TypeScriptNodeJsPlugin { after_compile: None, template: Some(String::from("// 在这里输入 TypeScript (Node.js) 代码")), timeout: Some(30), + console_type: Some(String::from("console")), } } diff --git a/src/App.vue b/src/App.vue index 0d454b6..c59bd45 100644 --- a/src/App.vue +++ b/src/App.vue @@ -33,13 +33,21 @@
- - + + + + + +
@@ -64,7 +72,8 @@ import {onMounted, onUnmounted, ref, watch} from 'vue' import AppHeader from './components/AppHeader.vue' import CodeEditor from './components/CodeEditor.vue' -import OutputPanel from './components/OutputPanel.vue' +import ConsoleOutput from './components/ConsoleOutput.vue' +import WebOutput from "./components/WebOutput.vue"; import StatusBar from './components/StatusBar.vue' import About from './components/About.vue' import Settings from './components/Settings.vue' @@ -103,6 +112,7 @@ const { envInfo, isLoadingEnvInfo, getLanguageDisplayName, + getCurrentConsoleType, handleLanguageChange, initialize } = useLanguageManager(code, clearOutput, toast) @@ -111,7 +121,6 @@ const { showAbout, showSettings, showUpdate, - activeTab, closeAbout, closeSettings, closeUpdate @@ -125,6 +134,7 @@ const { // 强制刷新 CodeEditor 组件的 key const editorConfigKey = ref(0) +const consoleType = ref('console') // 处理设置变更 const handleSettingsChanged = (config: any) => { @@ -149,6 +159,10 @@ watch(editorConfig, (newConfig) => { } }, {deep: true}) +watch(currentLanguage, () => { + consoleType.value = getCurrentConsoleType() +}) + const {initializeEventListeners, cleanupEventListeners} = useEventManager({ showAbout, showSettings, @@ -173,6 +187,7 @@ onMounted(async () => { await initialize() await loadEditorConfig() await initializeEventListeners() + consoleType.value = getCurrentConsoleType() // 触发 app-ready 事件,通知主进程 window.dispatchEvent(new CustomEvent('app-ready')) diff --git a/src/components/OutputPanel.vue b/src/components/ConsoleOutput.vue similarity index 100% rename from src/components/OutputPanel.vue rename to src/components/ConsoleOutput.vue diff --git a/src/components/WebOutput.vue b/src/components/WebOutput.vue new file mode 100644 index 0000000..40797df --- /dev/null +++ b/src/components/WebOutput.vue @@ -0,0 +1,121 @@ + + + diff --git a/src/components/setting/Language.vue b/src/components/setting/Language.vue index 429c104..68b96fb 100644 --- a/src/components/setting/Language.vue +++ b/src/components/setting/Language.vue @@ -77,9 +77,15 @@ @@ -98,6 +104,7 @@ import Label from '../../ui/Label.vue' import Input from '../../ui/Input.vue' import {useLanguageSettings} from '../../composables/useLanguageSettings' import type PluginConfig from '../../types/plugin' +import Select from "../../ui/Select.vue"; const emit = defineEmits<{ 'settings-changed': [config: PluginConfig] @@ -108,6 +115,7 @@ const { // 标签页状态 activeTab, tabsData, + consoleTypes, // 插件配置 activePlugin, diff --git a/src/composables/useAppState.ts b/src/composables/useAppState.ts index a9e2c2a..b2b659d 100644 --- a/src/composables/useAppState.ts +++ b/src/composables/useAppState.ts @@ -1,11 +1,10 @@ -import { ref } from 'vue' +import {ref} from 'vue' export function useAppState() { const showAbout = ref(false) const showSettings = ref(false) const showUpdate = ref(false) - const activeTab = ref('output') const closeAbout = () => { showAbout.value = false @@ -19,18 +18,12 @@ export function useAppState() showUpdate.value = false } - const setActiveTab = (tab: string) => { - activeTab.value = tab - } - return { showAbout, showSettings, showUpdate, - activeTab, closeAbout, closeSettings, - closeUpdate, - setActiveTab + closeUpdate } } diff --git a/src/composables/useCodeMirrorEditor.ts b/src/composables/useCodeMirrorEditor.ts index c521dab..9c0d438 100644 --- a/src/composables/useCodeMirrorEditor.ts +++ b/src/composables/useCodeMirrorEditor.ts @@ -5,6 +5,7 @@ import {go} from '@codemirror/lang-go' import {java} from '@codemirror/lang-java' import {rust} from '@codemirror/lang-rust' import {cpp} from '@codemirror/lang-cpp' +import {html} from '@codemirror/lang-html' import {shell} from '@codemirror/legacy-modes/mode/shell' import {swift} from '@codemirror/legacy-modes/mode/swift' import {kotlin, scala} from '@codemirror/legacy-modes/mode/clike' @@ -197,6 +198,8 @@ export function useCodeMirrorEditor(props: Props) return javascript({typescript: true}) case 'groovy': return StreamLanguage.define(groovy) + case 'html': + return html() default: return null } diff --git a/src/composables/useLanguageManager.ts b/src/composables/useLanguageManager.ts index 150ba39..7ac149a 100644 --- a/src/composables/useLanguageManager.ts +++ b/src/composables/useLanguageManager.ts @@ -1,6 +1,6 @@ -import { ref, type Ref } from 'vue' -import { invoke } from '@tauri-apps/api/core' -import { EnvInfo, Language, LanguageInfo } from '../types/app.ts' +import {ref, type Ref} from 'vue' +import {invoke} from '@tauri-apps/api/core' +import {EnvInfo, Language, LanguageInfo} from '../types/app.ts' export function useLanguageManager( code: Ref, @@ -27,6 +27,31 @@ export function useLanguageManager( return language ? language.name : languageValue } + // 获取当前语言的插件配置 + const getCurrentPluginConfig = () => { + if (!globalConfig.value) { + console.warn('globalConfig 还未加载,请先调用 initialize()') + return null + } + + if (!currentLanguage.value) { + console.warn('currentLanguage 为空,请先设置语言') + return null + } + + if (!globalConfig.value.plugins) { + console.warn('插件配置为空') + return null + } + + return globalConfig.value.plugins.find((p: any) => p.language === currentLanguage.value && p.enabled) || null + } + + const getCurrentConsoleType = () => { + const pluginConfig = getCurrentPluginConfig() + return pluginConfig?.console_type || 'console' + } + const refreshEnvInfo = async () => { // 确保有当前语言才进行检查 if (!currentLanguage.value) { @@ -74,7 +99,7 @@ export function useLanguageManager( supportedLanguages.value = languages.map((language) => ({ name: language.name, value: language.value, - svgUrl: `/icons/${ language.value.replace(/\d+$/, '') }.svg` + svgUrl: `/icons/${language.value.replace(/\d+$/, '')}.svg` })) } catch (error) { @@ -110,7 +135,7 @@ export function useLanguageManager( refreshEnvInfo() - toast.info(`已切换到 ${ getLanguageDisplayName(newLanguage) }`) + toast.info(`已切换到 ${getLanguageDisplayName(newLanguage)}`) } const initialize = async () => { @@ -139,10 +164,13 @@ export function useLanguageManager( return { currentLanguage, supportedLanguages, + globalConfig, envInfo, isLoadingEnvInfo, getLanguageDisplayName, handleLanguageChange, - initialize + initialize, + getCurrentPluginConfig, + getCurrentConsoleType } } diff --git a/src/composables/useLanguageSettings.ts b/src/composables/useLanguageSettings.ts index 98cb6f5..e3402a3 100644 --- a/src/composables/useLanguageSettings.ts +++ b/src/composables/useLanguageSettings.ts @@ -1,7 +1,7 @@ -import { computed, nextTick, ref, watch } from 'vue' -import { ContainerIcon, FileIcon, PickaxeIcon, Settings2 } from 'lucide-vue-next' -import { usePluginConfig } from './usePluginConfig' -import { useCodeMirrorEditor } from './useCodeMirrorEditor' +import {computed, nextTick, ref, watch} from 'vue' +import {ContainerIcon, FileIcon, PickaxeIcon, Settings2} from 'lucide-vue-next' +import {usePluginConfig} from './usePluginConfig' +import {useCodeMirrorEditor} from './useCodeMirrorEditor' export function useLanguageSettings(emit: any) { @@ -31,6 +31,8 @@ export function useLanguageSettings(emit: any) } ] + const consoleTypes = [{label: '控制台', value: 'console'}, {label: 'Web', value: 'web'}] + // 插件配置管理 const { activePlugin, @@ -101,12 +103,12 @@ export function useLanguageSettings(emit: any) if (newLanguage) { await updateExtensions() } - }, { immediate: false }) + }, {immediate: false}) // 监听插件配置变化 watch(() => pluginConfig.value?.template, (newTemplate) => { console.log('Template changed:', newTemplate) - }, { immediate: false }) + }, {immediate: false}) // 初始化所有功能 const initialize = async () => { @@ -132,6 +134,7 @@ export function useLanguageSettings(emit: any) // 标签页状态 activeTab, tabsData, + consoleTypes, // 插件配置 activePlugin, diff --git a/src/types/plugin.ts b/src/types/plugin.ts index 10ef1ff..5455d9d 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -9,4 +9,5 @@ export default interface PluginConfig run_command?: string // 插件执行的命令,例如 "python2 $filename" template?: string // 插件的模板 timeout?: number // 插件的超时时间 + console_type?: string // 插件的输出类型 }