- Local terminal (node-pty) + SSH sessions (ssh2) with unified data plane - dockview split panes, per-group '+' tab bar button, layout templates - Session replay buffer (late-subscriber catch-up), host key pinning, credential encryption via safeStorage - 12 builtin themes + custom theme editor, system font enumeration - Keyword highlighting: regex rules with priority, ANSI truecolor injection, chunk-boundary-safe stream (carry-over of partial escape sequences) - Dark antd theme app-wide, settings dialog redesign, error boundary - Tests: ssh loopback, session e2e, highlight split-chunk regression
82 lines
4.3 KiB
Markdown
82 lines
4.3 KiB
Markdown
# OpenTerminal
|
||
|
||
一个受 XTerminal 启发的开源终端应用:本地终端 + 分屏管理 + 字体/主题定制。Electron + React + TypeScript。
|
||
|
||
对应调研背景与逆向分析记录见 `research/`(XTerminal 5.7.17 解包产物与功能清单)。
|
||
|
||
## 快速开始
|
||
|
||
```bash
|
||
npm install # 已安装可跳过
|
||
npm run dev # 开发模式(热更新)
|
||
npm run build # 生产构建到 out/
|
||
npm run typecheck # 全量类型检查
|
||
```
|
||
|
||
> Electron 二进制下载失败时:`ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ node node_modules/electron/install.js`
|
||
|
||
## 已实现功能(M1+M2)
|
||
|
||
**终端核心**
|
||
- 本地终端(node-pty,Windows PowerShell / macOS zsh / Linux bash 自动探测)
|
||
- xterm.js 渲染:WebGL 高性能模式,加载失败/上下文丢失自动降级 DOM
|
||
- 会话生命周期:退出遮罩显示退出码、关闭按钮;窗口关闭时回收全部会话
|
||
- 搜索(Ctrl+F 内嵌搜索条、全部高亮、n/N 计数)
|
||
- 剪贴板(Ctrl+Shift+C/V、可选选中即复制)
|
||
- 粘贴风险确认(多行/长文本需手动确认,可关闭)
|
||
- 字体/字号/字重/字距/行高/回滚行数/光标样式实时生效
|
||
|
||
**SSH 远程会话(M2)**
|
||
- ssh2 实现:密码 / 私钥(文件路径或粘贴内容)/ SSH Agent 三种认证
|
||
- 连接管理器:左侧书签栏(分组手风琴)、双击连接、新建/编辑/删除对话框
|
||
- 凭据安全:密码/私钥/口令经 Electron safeStorage(DPAPI)加密后落盘,渲染层永远接触不到明文密钥;支持「连接时询问密码」模式
|
||
- 主机指纹校验(known hosts 固定):首次连接确认、指纹变更红色告警、30s 无响应自动拒绝
|
||
- 连接中状态展示、失败原因提示、lastConnectedAt 记录
|
||
- 会话数据面与本地终端完全统一(写/缩放/关闭/退出事件同通道)
|
||
|
||
**分屏与布局**
|
||
- dockview 标签系统:水平/垂直分屏、拖拽重排、标签右键菜单(关闭/关闭其他/关闭右侧)
|
||
- 布局模板:把当前分屏保存为模板、一键应用(自动重建会话)、可删除
|
||
- 空态引导页
|
||
|
||
**设置与主题**
|
||
- 12 款内置主题(Dracula / One Half / Solarized / Gruvbox / Nord / Monokai / GitHub / Afterglow / Material 等)
|
||
- 自定义主题编辑器:16 色 ANSI 调色板 + 前景/背景/光标/选区色,实时预览
|
||
- 系统字体枚举(font-list)+ 内置默认字体栈
|
||
- 设置持久化(userData/settings.json,原子写入)+ 多窗口实时同步
|
||
|
||
**测试**
|
||
- `node tests/ssh-loopback.mjs` — ssh2 客户端/服务端回环(认证、shell、数据、resize、指纹)
|
||
- `node tests/ssh-session-e2e.mjs` — 真实会话路由层端到端(需先跑 esbuild 打包命令,见脚本头注释)
|
||
|
||
## 架构
|
||
|
||
```
|
||
src/
|
||
├── shared/ # 主/渲染进程共享契约(IPC 通道、设置、主题模型)
|
||
│ ├── ipc.ts # 通道名 + 负载类型
|
||
│ ├── api.ts # window.api 接口(preload 暴露面)
|
||
│ ├── settings.ts # AppSettings / 默认值
|
||
│ └── theme.ts # TerminalTheme / 内置主题
|
||
├── main/ # 主进程
|
||
│ ├── pty.ts # PTY 会话池(node-pty)→ 广播 PTY_DATA/PTY_EXIT
|
||
│ ├── settingsStore.ts # JSON 持久化 + 深合并兜底
|
||
│ ├── layouts.ts # 布局模板存储(userData/layouts/*.json)
|
||
│ └── ipc.ts # 全部 ipcMain 注册
|
||
├── preload/index.ts # contextBridge → window.api
|
||
└── renderer/src/
|
||
├── terminal/ # TerminalView:xterm 封装(渲染器/搜索/剪贴板/粘贴确认)
|
||
├── workspace/ # dockview 工作区:工具栏/分屏/会话生命周期/布局模板
|
||
├── settings/ # zustand store + 设置对话框
|
||
└── theme/editor/ # 自定义主题编辑器
|
||
```
|
||
|
||
关键设计:**契约先行** —— `src/shared/` 是唯一契约源,主/预载/渲染三端各自实现,模块间零横向依赖(terminal 不感知 workspace,settings 不感知 terminal)。
|
||
|
||
## 数据位置
|
||
|
||
- 设置:`%APPDATA%/OpenTerminal/settings.json`
|
||
- 布局模板:`%APPDATA%/OpenTerminal/layouts/*.json`
|
||
- SSH 连接书签:`%APPDATA%/OpenTerminal/connections.json`(密钥字段 DPAPI 加密)
|
||
- 主机指纹:`%APPDATA%/OpenTerminal/ssh_known_hosts.json`
|