Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8db2bb7
feat: JSON/XML 运行改为格式化+校验而非 cat
qianmoQ Jun 5, 2026
6b77f91
feat: JSON 运行改用定制 JSON 树视图,撤销校验方案
qianmoQ Jun 5, 2026
fe7dafa
feat: 配置页输出类型增加 JSON 选项
qianmoQ Jun 5, 2026
38d4073
feat: Markdown 独立输出类型(运行后渲染预览)
qianmoQ Jun 5, 2026
fedce4f
fix: Markdown 渲染支持内嵌 HTML(DOMPurify 净化防 XSS)
qianmoQ Jun 5, 2026
21174e7
perf: 修复运行后约 3 秒卡顿(执行历史写库阻塞)
qianmoQ Jun 6, 2026
efccf43
fix: 语言变化时同步输出类型,修复 JSON/Markdown 视图不激活
qianmoQ Jun 6, 2026
beed11b
fix: 运行 Markdown/JSON 卡死——渲染防抖
qianmoQ Jun 6, 2026
d03949c
feat: XML 独立输出类型(可折叠 XML 树视图)
qianmoQ Jun 6, 2026
6b98bbb
feat: YAML 独立输出类型(复用 JSON 树视图)
qianmoQ Jun 6, 2026
cfd5c5a
feat: JSON 视图支持文本/可视化双模式
qianmoQ Jun 6, 2026
0155773
feat: JSON 可视化关系图模式
qianmoQ Jun 6, 2026
9a13483
feat: YAML 可视化关系图模式
qianmoQ Jun 6, 2026
3835f6c
feat: XML 可视化关系图模式
qianmoQ Jun 6, 2026
78f2a3b
feat: GitHub Actions 工作流可视化
qianmoQ Jun 6, 2026
e3f99a0
docs: 重写 README,清晰呈现定位与完整功能
qianmoQ Jun 6, 2026
8b44895
feat: 状态栏增加终端切换按钮(带快捷键提示)
qianmoQ Jun 6, 2026
af81408
style: 状态栏终端按钮不再显示快捷键文字(仅图标,快捷键保留在 hover 提示)
qianmoQ Jun 6, 2026
82edd4c
feat: 新增 SQL 语言插件
qianmoQ Jun 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 129 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,125 @@
<div align="center">
<img src="public/codeforge.svg" width=100 />
<img src="public/codeforge.svg" width="100" />

<h1 style="margin-top: -20px;">CodeForge</h1>
<h1 style="margin-top: -10px;">CodeForge</h1>

CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发者、学生和编程爱好者设计。
**一款现代化的桌面端多语言代码编辑器与运行器**

集「文件/项目编辑 · 一键运行 · AI 助手 · Git 集成 · 集成终端 · 结构化数据可视化」于一身,
让你在一个轻量优雅的桌面应用里完成编写、运行、调试与协作。

<p>
<img alt="version" src="https://img.shields.io/badge/version-26.1.0-blue" />
<img alt="platform" src="https://img.shields.io/badge/platform-macOS%20%7C%20Windows%20%7C%20Linux-555" />
<img alt="stack" src="https://img.shields.io/badge/Tauri%202-Vue%203-FFC131" />
<img alt="license" src="https://img.shields.io/badge/license-MIT-green" />
</p>
</div>

## 演示视频

📹 [下载演示视频](https://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/codeforge/codeforge.mp4) (点击下载或观看)

> 注:由于 GitHub 不支持直接播放视频,请下载或点击链接查看

## 特性

- 🚀 **即时执行** - 一键运行代码
- 💻 **现代界面** - 简洁优雅的用户体验
- 📝 **智能编辑** - 代码高亮、行号、自动缩进
- 📊 **执行监控** - 实时显示执行时间和结果
- 🔧 **插件架构** - 可扩展的语言支持系统

## 支持的语言

<div style="display: flex; align-items: center; justify-content: center;">
<img src="public/icons/c.svg" width="60" alt="C">
<img src="public/icons/cangjie.svg" width="60" alt="Cangjie">
<img src="public/icons/clojure.svg" width="60" alt="Clojure">
<img src="public/icons/cpp.svg" width="60" alt="C++">
<img src="public/icons/css.svg" width="60" alt="CSS">
<img src="public/icons/go.svg" width="60" alt="Go">
<img src="public/icons/groovy.svg" width="60" alt="Groovy">
<img src="public/icons/haskell.svg" width="60" alt="Haskell">
<img src="public/icons/html.svg" width="60" alt="HTML">
<img src="public/icons/java.svg" width="60" alt="Java">
<img src="public/icons/javascript-browser.svg" width="60" alt="JavaScript (Browser)">
<img src="public/icons/javascript-jquery.svg" width="60" alt="JavaScript (jQuery)">
<img src="public/icons/javascript-nodejs.svg" width="60" alt="JavaScript (Node.js)">
<img src="public/icons/kotlin.svg" width="60" alt="Kotlin">
<img src="public/icons/lua.svg" width="60" alt="Lua">
<img src="public/icons/nodejs.svg" width="60" alt="Node.js">
<img src="public/icons/objective-c.svg" width="60" alt="Objective-C">
<img src="public/icons/objective-cpp.svg" width="60" alt="Objective-C++">
<img src="public/icons/php.svg" width="60" alt="PHP">
<img src="public/icons/python.svg" width="60" alt="Python 2">
<img src="public/icons/python.svg" width="60" alt="Python 3">
<img src="public/icons/r.svg" width="60" alt="R">
<img src="public/icons/ruby.svg" width="60" alt="Ruby">
<img src="public/icons/rust.svg" width="60" alt="Rust">
<img src="public/icons/shell.svg" width="60" alt="Shell">
<img src="public/icons/svg.svg" width="60" alt="SVG">
<img src="public/icons/swift.svg" width="60" alt="Swift">
<img src="public/icons/typescript.svg" width="60" alt="TypeScript">
<img src="public/icons/typescript-browser.svg" width="60" alt="TypeScript (Browser)">
<img src="public/icons/typescript-nodejs.svg" width="60" alt="TypeScript (Node.js)">
---

## 📹 演示视频

[下载演示视频](https://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/codeforge/codeforge.mp4)(点击下载或观看)

> GitHub 不支持直接播放视频,请下载或点击链接查看。

---

## ✨ 核心功能

### 📂 编辑与项目
- **文件树侧栏 + 多标签编辑** —— 打开文件夹,像 IDE 一样浏览、编辑整个项目
- **面包屑路径导航** —— 点击任意层级在系统文件管理器中定位
- **命令面板**(`Cmd/Ctrl + Shift + P`)—— 一处入口直达所有命令
- **快速打开**(`Cmd/Ctrl + P`)—— 模糊匹配 + 最近文件优先
- **符号大纲**(`Cmd/Ctrl + Shift + O`)、**跳转到行**(`Cmd/Ctrl + G`)
- **代码片段** —— 自定义前缀,输入后按 `Tab` 展开(`$0` 为光标落点)
- **会话恢复** —— 重启自动恢复上次的文件夹与标签页
- **深色模式** —— 跟随系统 / 浅色 / 深色,编辑器主题同步切换

### ▶️ 运行与调试
- **一键运行 / 按文件就地运行**,实时流式输出、执行耗时统计
- **运行选中片段**(`Cmd/Ctrl + Shift + Enter`)
- **监听模式** —— 保存后自动重跑
- **运行输入** —— 自定义参数 / stdin / 环境变量,并按文件记忆
- **执行历史** —— 持久化保存,可一键重跑与还原

### 📊 结构化数据可视化
- **JSON / XML / YAML** —— 可折叠**层级树**,以及卡片 + 连线的**关系图**两种可视化
- **Markdown** —— 实时渲染预览(支持内嵌 HTML,DOMPurify 净化防 XSS)
- **GitHub Actions 工作流** —— 自动识别并渲染为 **Jobs 依赖 DAG 图**(触发事件 → 各 Job → Steps)

### 🤖 AI 助手
- **多服务商** —— Claude (Anthropic) / OpenAI / DeepSeek
- **AI 代码预测** —— 编辑器内幽灵补全,`Tab` 接受
- **解释代码 / 生成测试 / 格式化代码** —— 一键发起,应用前可 diff 预览确认
- **报错分析、自然语言生成代码、生成 Git 提交信息**
- **对话与执行历史绑定** —— 每次执行的 AI 讨论可追溯

### 🔱 Git 集成
- **源代码管理面板** —— 暂存 / 提交 / 推送 / 分支切换,AI 一键生成提交信息
- **文件树状态徽标**(M / A / D / U)
- **编辑器行内差异标记** —— 相对 HEAD 的增 / 改 / 删

### 🔎 搜索与终端
- **文件夹内搜索与替换**(`Cmd/Ctrl + Shift + F`)
- **集成终端** —— 真实 shell、多标签、可拖拽改高度(`` Cmd/Ctrl + ` ``)

---

## 🧩 支持的语言

可运行语言均采用**插件化架构**,每种语言独立实现;JSON / XML / YAML / Markdown / 纯文本为编辑与可视化类型。

<div align="center">
<img src="public/icons/python.svg" width="48" title="Python 2 / 3" />
<img src="public/icons/nodejs.svg" width="48" title="Node.js" />
<img src="public/icons/typescript.svg" width="48" title="TypeScript" />
<img src="public/icons/javascript-nodejs.svg" width="48" title="JavaScript (Node.js)" />
<img src="public/icons/javascript-browser.svg" width="48" title="JavaScript (Browser)" />
<img src="public/icons/javascript-jquery.svg" width="48" title="JavaScript (jQuery)" />
<img src="public/icons/go.svg" width="48" title="Go" />
<img src="public/icons/rust.svg" width="48" title="Rust" />
<img src="public/icons/java.svg" width="48" title="Java" />
<img src="public/icons/kotlin.svg" width="48" title="Kotlin" />
<img src="public/icons/scala.svg" width="48" title="Scala" />
<img src="public/icons/groovy.svg" width="48" title="Groovy" />
<img src="public/icons/clojure.svg" width="48" title="Clojure" />
<img src="public/icons/c.svg" width="48" title="C" />
<img src="public/icons/cpp.svg" width="48" title="C++" />
<img src="public/icons/objective-c.svg" width="48" title="Objective-C" />
<img src="public/icons/objective-cpp.svg" width="48" title="Objective-C++" />
<img src="public/icons/swift.svg" width="48" title="Swift" />
<img src="public/icons/ruby.svg" width="48" title="Ruby" />
<img src="public/icons/php.svg" width="48" title="PHP" />
<img src="public/icons/r.svg" width="48" title="R" />
<img src="public/icons/lua.svg" width="48" title="Lua" />
<img src="public/icons/haskell.svg" width="48" title="Haskell" />
<img src="public/icons/cangjie.svg" width="48" title="Cangjie" />
<img src="public/icons/shell.svg" width="48" title="Shell" />
<img src="public/icons/applescript.svg" width="48" title="AppleScript" />
<img src="public/icons/html.svg" width="48" title="HTML" />
<img src="public/icons/css.svg" width="48" title="CSS" />
<img src="public/icons/svg.svg" width="48" title="SVG" />
<img src="public/icons/json.svg" width="48" title="JSON" />
<img src="public/icons/xml.svg" width="48" title="XML" />
<img src="public/icons/yaml.svg" width="48" title="YAML" />
<img src="public/icons/markdown.svg" width="48" title="Markdown" />
<img src="public/icons/text.svg" width="48" title="纯文本" />
</div>

## 安装
<div align="center">

**系统要求:**
`Python` · `Node.js` · `TypeScript` · `JavaScript` · `Go` · `Rust` · `Java` · `Kotlin` · `Scala` · `Groovy` · `Clojure` · `C` · `C++` · `Objective-C/C++` · `Swift` · `Ruby` · `PHP` · `R` · `Lua` · `Haskell` · `Cangjie` · `Shell` · `AppleScript` · `HTML` · `CSS` · `SVG` · `JSON` · `XML` · `YAML` · `Markdown` · `Text`

- Node.js 18+
- Rust 1.8+
- Tauri 2.x
- Vue 3.x
</div>

**构建步骤:**
---

## 🚀 安装与构建

**环境要求:** Node.js 22+ · Rust 1.8+ · pnpm

```bash
# 克隆项目
Expand All @@ -81,12 +136,23 @@ pnpm tauri dev
pnpm tauri build
```

## 技术栈
---

## 🛠 技术栈

| 层 | 技术 |
| --- | --- |
| 前端 | Vue 3 · TypeScript · Tailwind CSS · CodeMirror 6 |
| 后端 | Rust · Tauri 2 |
| 存储 | SQLite(执行历史 / AI 对话 / 代码片段 / 应用配置统一入库) |
| 架构 | 插件化语言支持系统 |

---

## 🤝 贡献与反馈

- **前端:** Vue 3 + TypeScript + Tailwind CSS
- **后端:** Rust + Tauri
- **架构:** 插件化语言支持系统
欢迎提交 Issue 与 PR:<https://github.com/devlive-community/codeforge/issues>

## 许可证
## 📄 许可证

MIT License
[MIT License](LICENSE)
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@codemirror/lang-php": "^6.0.2",
"@codemirror/lang-python": "^6.2.1",
"@codemirror/lang-rust": "^6.0.2",
"@codemirror/lang-sql": "^6.10.0",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/lang-yaml": "^6.1.3",
"@codemirror/language": "^6.11.2",
Expand All @@ -38,6 +39,8 @@
"@xterm/addon-fit": "^0.11.0",
"@xterm/xterm": "^6.0.0",
"codemirror": "^6.0.2",
"dompurify": "^3.4.8",
"js-yaml": "^4.2.0",
"lodash-es": "^4.17.21",
"lucide-vue-next": "^0.539.0",
"markdown-it": "^14.2.0",
Expand All @@ -48,6 +51,7 @@
"devDependencies": {
"@tailwindcss/postcss": "^4.1.11",
"@tauri-apps/cli": "^2",
"@types/js-yaml": "^4.0.9",
"@types/lodash-es": "^4.17.12",
"@types/markdown-it": "^14.1.2",
"@vitejs/plugin-vue": "^5.2.1",
Expand Down
6 changes: 6 additions & 0 deletions public/icons/sql.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src-tauri/src/ai_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ impl AiHistory {
let db_path = get_codeforge_db_path()?;
let conn = Connection::open(&db_path).map_err(|e| format!("打开数据库失败: {}", e))?;
let _ = conn.pragma_update(None, "journal_mode", "WAL");
let _ = conn.pragma_update(None, "synchronous", "NORMAL");
let _ = conn.busy_timeout(std::time::Duration::from_secs(5));
// 清理早期错误结构的旧表
let _ = conn.execute("DROP TABLE IF EXISTS ai_conversations", []);
conn.execute(
Expand Down
8 changes: 7 additions & 1 deletion src-tauri/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ impl ExecutionHistory {
let conn =
Connection::open(&db_path).map_err(|e| format!("打开执行历史数据库失败: {}", e))?;

// 与其它连接(ai/kv/snippets)共用同一个库文件:统一 WAL + NORMAL + busy_timeout,
// 避免并发写入(如运行时同时有 kv 写入)相互阻塞导致 insert 卡顿
let _ = conn.pragma_update(None, "journal_mode", "WAL");
let _ = conn.pragma_update(None, "synchronous", "NORMAL");
let _ = conn.busy_timeout(std::time::Duration::from_secs(5));

conn.execute(
"CREATE TABLE IF NOT EXISTS execution_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
Expand Down Expand Up @@ -627,7 +633,7 @@ pub async fn execute_code(
return Ok(result);
}
Ok(None) => {
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
}
Err(e) => {
let _ = child.kill();
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/kv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ impl KvStore {
let db_path = get_codeforge_db_path()?;
let conn = Connection::open(&db_path).map_err(|e| format!("打开数据库失败: {}", e))?;
let _ = conn.pragma_update(None, "journal_mode", "WAL");
let _ = conn.pragma_update(None, "synchronous", "NORMAL");
let _ = conn.busy_timeout(std::time::Duration::from_secs(5));
conn.execute(
"CREATE TABLE IF NOT EXISTS kv_store (
key TEXT PRIMARY KEY,
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/src/plugins/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ impl LanguagePlugin for JsonPlugin {
before_compile: None,
extension: String::from("json"),
execute_home: None,
// 输出原始 JSON 内容,由前端 JSON 视图(可折叠树)渲染
run_command: Some(String::from("cat $filename")),
after_compile: None,
template: Some(String::from("{\n \n}")),
timeout: Some(30),
console_type: Some(String::from("console")),
console_type: Some(String::from("json")),
icon_path: None,
}
}
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/plugins/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::plugins::ruby::RubyPlugin;
use crate::plugins::rust::RustPlugin;
use crate::plugins::scala::ScalaPlugin;
use crate::plugins::shell::ShellPlugin;
use crate::plugins::sql::SqlPlugin;
use crate::plugins::svg::SvgPlugin;
use crate::plugins::swift::SwiftPlugin;
use crate::plugins::text::TextPlugin;
Expand Down Expand Up @@ -75,6 +76,7 @@ impl PluginManager {
("yaml".to_string(), Box::new(YamlPlugin)),
("markdown".to_string(), Box::new(MarkdownPlugin)),
("text".to_string(), Box::new(TextPlugin)),
("sql".to_string(), Box::new(SqlPlugin)),
("php".to_string(), Box::new(PHPPlugin)),
("r".to_string(), Box::new(RPlugin)),
("cangjie".to_string(), Box::new(CangjiePlugin)),
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/src/plugins/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ impl LanguagePlugin for MarkdownPlugin {
before_compile: None,
extension: String::from("md"),
execute_home: None,
// 输出原始 Markdown,由前端渲染为预览
run_command: Some(String::from("cat $filename")),
after_compile: None,
template: Some(String::from("# 标题\n\n在这里输入 Markdown 内容\n")),
timeout: Some(30),
console_type: Some(String::from("console")),
console_type: Some(String::from("markdown")),
icon_path: None,
}
}
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ pub mod ruby;
pub mod rust;
pub mod scala;
pub mod shell;
pub mod sql;
pub mod svg;
pub mod swift;
pub mod text;
Expand Down
57 changes: 57 additions & 0 deletions src-tauri/src/plugins/sql.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use super::{LanguagePlugin, PluginConfig};
use std::vec;

pub struct SqlPlugin;

impl LanguagePlugin for SqlPlugin {
fn get_order(&self) -> i32 {
28
}

fn get_language_name(&self) -> &'static str {
"SQL"
}

fn get_language_key(&self) -> &'static str {
"sql"
}

fn get_file_extension(&self) -> String {
self.get_config()
.map(|config| config.extension.clone())
.unwrap_or_else(|| "sql".to_string())
}

fn get_version_args(&self) -> Vec<&'static str> {
vec!["--version"]
}

fn get_path_command(&self) -> String {
"sqlite3".to_string()
}

fn get_default_config(&self) -> PluginConfig {
PluginConfig {
enabled: true,
language: String::from("sql"),
before_compile: None,
extension: String::from("sql"),
execute_home: None,
// 在内存 SQLite 中执行脚本(需要本机有 sqlite3)
run_command: Some(String::from("sqlite3 :memory: .read $filename")),
after_compile: None,
template: Some(String::from(
"-- 在这里输入 SQL(默认在内存 SQLite 中执行)\nSELECT 'Hello, CodeForge' AS message;\n",
)),
timeout: Some(30),
console_type: Some(String::from("console")),
icon_path: None,
}
}

fn get_default_command(&self) -> String {
self.get_config()
.and_then(|config| config.run_command.clone())
.unwrap_or_else(|| "sqlite3".to_string())
}
}
Loading
Loading