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 代码示例
+
+
+
+
+
+
+
+
+
+
✅ 基本输出 (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)
+
+ - 1. 苹果 🍎
+ - 2. 香蕉 🍌
+ - 3. 橙子 🍊
+ - 4. 葡萄 🍇
+
+
+
+
+
+
📊 成绩评估 (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 @@
+
+
+
+
+
+
+
+
+
+ {{ executionTime }} 毫秒
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
没有Web内容
+
+ 运行 HTML、CSS 或 JavaScript 代码来查看网页效果
+
+
+
+
+
+
+
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 // 插件的输出类型
}