14 KiB
14 KiB
MarkLite - 设计文档
1. 项目概述
MarkLite 是一款轻量级的 Windows 本地 Markdown 编辑器桌面应用程序。基于 Electron 框架构建,提供简洁现代的用户界面,支持多标签页、Markdown 文件的打开、编辑和实时预览,支持亮色/暗色主题切换,支持搜索替换和文件树侧边栏。
2. 技术架构
2.1 技术栈
| 组件 | 技术选型 | 说明 |
|---|---|---|
| 桌面框架 | Electron v28 | 跨平台桌面应用框架 |
| 前端 | HTML + CSS + JavaScript | 原生前端技术,无框架依赖 |
| Markdown 解析 | marked.js v12 | 高性能 Markdown 解析库(本地离线) |
| 代码高亮 | highlight.js v11 | 代码块语法高亮(本地离线) |
| 打包 | electron-builder | 生成 Windows NSIS 安装包 |
2.2 进程架构
┌─────────────────────────────────────────┐
│ Main Process (main.js) │
│ - 窗口管理 │
│ - 文件系统操作 (fs) │
│ - 文件监听 (fs.watch) │
│ - 目录树读取与监听 │
│ - 未保存提醒拦截 │
│ - IPC 通信主端 │
└──────────────┬──────────────────────────┘
│ IPC (contextBridge)
┌──────────────▼──────────────────────────┐
│ Preload Script (preload.js) │
│ - 安全的 API 桥接 │
│ - exposeInMainWorld │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Renderer Process (renderer/) │
│ - 多标签页管理 │
│ - UI 渲染(亮色/暗色主题) │
│ - Markdown 编辑与预览 │
│ - 搜索替换(高亮、正则、大小写) │
│ - 文件树侧边栏 │
│ - 拖拽文件处理 │
│ - 快捷键处理 │
│ - 用户设置持久化 (localStorage) │
└─────────────────────────────────────────┘
2.3 安全模型
contextIsolation: true+nodeIntegration: false- 通过
contextBridge.exposeInMainWorld安全暴露 API - CSP 策略:
default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; img-src 'self' data: - 渲染进程无法直接访问 Node.js API
3. 功能设计
3.1 核心功能
-
多标签页
- Ctrl+T 新建空白标签
- Ctrl+W 关闭当前标签(未保存时确认)
- Ctrl+Tab / Ctrl+Shift+Tab 切换标签
- 点击标签切换,hover 显示关闭按钮
- 同一文件不会重复打开(自动切换到已有标签)
- 每个标签独立保存:内容、滚动位置、光标位置、修改状态
-
文件打开
- 工具栏 → 打开按钮(支持 .md / .txt / .markdown)
- 拖拽文件到窗口打开(支持多文件同时拖入)
- 支持 Windows 文件关联(双击 .md 文件打开)
- 支持命令行参数传入文件路径
-
文件保存
- Ctrl+S 快捷键保存
- 工具栏 → 保存按钮
- Ctrl+Shift+S 另存为
-
实时预览
- 左侧编辑器 + 右侧预览(默认分屏模式)
- 编辑 150ms 防抖后更新预览
- 基于 DOM 位置映射的滚动同步
-
视图模式
- 编辑+预览(Split View)— Ctrl+1
- 纯编辑模式 — Ctrl+2
- 纯预览模式 — Ctrl+3
- 记忆上次使用的视图模式(localStorage)
-
文件修改检测
- 主进程通过
fs.watch监听当前活动标签的文件 - 外部修改时显示黄色提示横幅
- 支持「重新加载」或「忽略」
- 切换标签时自动切换监听目标
- 主进程通过
-
未保存提醒
- 关闭窗口时检测所有标签的未保存修改
- 弹出确认对话框,防止误操作
- 主进程 5 秒超时兜底,防止渲染进程无响应时窗口卡死
-
暗色主题
- 工具栏右侧月亮/太阳图标切换
- CSS 变量驱动,一键切换整套配色
- 主题偏好持久化(localStorage)
-
搜索替换
- Ctrl+F 打开搜索栏,Ctrl+H 打开搜索+替换栏
- 实时高亮所有匹配项,当前匹配用不同颜色标识
- Enter / Shift+Enter 导航下一个/上一个匹配
- 区分大小写(Alt+C)、正则表达式(Alt+R)切换
- 替换当前(Ctrl+Shift+G)、全部替换(Ctrl+Shift+H)
- 自动将选中文本填充到搜索框
- Esc 关闭搜索栏
-
文件树侧边栏
- 工具栏按钮打开文件夹选择对话框
- 递归读取目录结构,只显示 .md/.markdown/.txt 文件
- 自动跳过 node_modules、.git、dist 等无关目录
- 点击文件夹展开/折叠,点击文件在新标签页打开
- 已打开的文件自动切换到对应标签
- fs.watch 监听目录变化,自动刷新树
- 侧边栏折叠状态持久化(localStorage)
3.2 UI 设计
色彩方案(亮色)
| 角色 | 色值 |
|---|---|
| 主色调 | #1a73e8 |
| 背景色 | #ffffff |
| 次级背景 | #f8f9fa |
| 三级背景 | #f1f3f4 |
| 文字色 | #333333 |
| 次级文字 | #5f6368 |
| 代码块背景 | #f6f8fa |
| 边框色 | #e1e4e8 |
色彩方案(暗色)
| 角色 | 色值 |
|---|---|
| 主色调 | #8ab4f8 |
| 背景色 | #1e1e1e |
| 次级背景 | #252526 |
| 三级背景 | #2d2d2d |
| 文字色 | #d4d4d4 |
| 次级文字 | #9e9e9e |
| 代码块背景 | #2d2d2d |
| 边框色 | #3e3e3e |
字体
- UI 字体: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
- 编辑器字体: "Cascadia Code", "Fira Code", "JetBrains Mono", Consolas, monospace
- 预览字体: 同 UI 字体
布局
┌──────────────────────────────────────────────────────────────────────────┐
│ MarkLite - filename.md ─ □ ✕ │
├──────────────────────────────────────────────────────────────────────────┤
│ 📁 打开 │ 💾 保存 │ ⬜ 分屏 │ ✏️ 编辑 │ 👁 预览 │ 🌙 │
├──────────────────────────────────────────────────────────────────────────┤
│ [file1.md] [file2.md] [未命名] [+] │
├──────────────────────────────────────────────────────────────────────────┤
│ ⚠️ 文件已被外部程序修改 [重新加载] [忽略] │
├──────────┬─────────────────────────┬─────────────────────────────────────┤
│ 资源管理器│ │ │
│ ▼ project │ 🔍 查找... 2/5 │ Title │
│ 📁 src │ [替换... ] [替换][全部]│ ─────── │
│ 📄 file1│ │ │
│ 📄 file2│ 1 # Title │ Title │
│ 📁 lib │ 2 │ ─────── │
│ │ 3 content... │ content... │
│ │ 4 │ │
├──────────┴─────────────────────────┴─────────────────────────────────────┤
│ filename.md │ UTF-8 │ Markdown │ 1.2 KB │ 行 3, 列 1 │
└──────────────────────────────────────────────────────────────────────────┘
4. 文件结构
MarkLite/
├── package.json # 项目配置与依赖
├── main.js # Electron 主进程
├── preload.js # 预加载脚本(IPC 桥接)
├── renderer/
│ ├── index.html # 主页面结构(含侧边栏、搜索栏)
│ ├── style.css # UI 样式(亮色/暗色主题、侧边栏、搜索栏)
│ └── renderer.js # 渲染进程逻辑(标签页、编辑、预览、搜索、文件树)
├── lib/
│ ├── marked.min.js # Markdown 解析库(离线)
│ ├── highlight.min.js # 代码高亮库(离线)
│ └── highlight-github.css # 代码高亮主题
├── assets/
│ └── icon.ico # 应用图标(多尺寸)
├── DESIGN.md # 设计文档(本文件)
├── DEVSETUP.md # 开发环境配置指南
├── README.md # 项目说明
├── LICENSE # MIT 许可证
└── .gitignore # Git 忽略文件
5. IPC 通信设计
5.1 渲染进程 → 主进程(invoke)
| 通道 | 参数 | 返回值 | 说明 |
|---|---|---|---|
dialog:openFile |
无 | { filePath, content } 或 null |
打开文件对话框 |
file:read |
filePath |
{ success, content } |
读取文件内容 |
file:save |
{ filePath, content } |
{ success, filePath } |
保存文件 |
file:saveAs |
{ content } |
{ success, filePath } |
另存为 |
file:getCurrentPath |
无 | string | null |
获取当前文件路径 |
file:stats |
filePath |
{ success, size, mtime } |
获取文件元信息 |
file:reload |
无 | { success, content, filePath } |
重新加载当前文件 |
tab:switched |
filePath |
无 | 通知主进程切换活动文件 |
window:forceClose |
无 | 无 | 强制关闭窗口(跳过未保存检查) |
dir:readTree |
dirPath |
{ success, tree, rootPath } |
递归读取目录树 |
dir:openDialog |
无 | string | null |
打开文件夹选择对话框 |
dir:watch |
dirPath |
无 | 监听目录变化 |
dir:unwatch |
无 | 无 | 停止监听目录变化 |
5.2 主进程 → 渲染进程(send)
| 通道 | 数据 | 说明 |
|---|---|---|
file:openInTab |
{ filePath, content } |
在新标签中打开文件 |
file:opened |
{ filePath, content } |
文件已打开(兼容旧路径) |
file:externallyModified |
filePath |
文件被外部修改 |
menu:save |
无 | 菜单触发保存 |
menu:saveAs |
无 | 菜单触发另存为 |
menu:viewMode |
mode |
菜单切换视图模式 |
window:confirmClose |
无 | 请求确认关闭 |
window:closing |
无 | 窗口即将关闭 |
sidebar:dirChanged |
无 | 目录结构变化,通知渲染进程刷新树 |
6. 标签页数据模型
每个标签页在渲染进程中维护独立状态:
{
id: Number, // 唯一标识
filePath: String | null, // 文件路径(未命名标签为 null)
content: String, // 编辑器内容
isModified: Boolean, // 是否已修改
scrollTop: Number, // 编辑器滚动位置
scrollLeft: Number,
selectionStart: Number, // 光标选区
selectionEnd: Number,
previewScrollTop: Number // 预览面板滚动位置
}
切换标签时自动保存当前状态、恢复目标状态。
7. 数据持久化
通过 localStorage 存储用户偏好,key 为 marklite-settings:
{
"darkMode": false,
"viewMode": "split",
"splitRatio": 50,
"sidebarCollapsed": false
}
| 字段 | 类型 | 说明 |
|---|---|---|
darkMode |
boolean | 暗色主题开关 |
viewMode |
string | 视图模式:split / editor / preview |
splitRatio |
number | 分屏比例(20~80) |
sidebarCollapsed |
boolean | 侧边栏是否折叠 |
8. Markdown 渲染支持
支持标准 Markdown 和 GFM(GitHub Flavored Markdown):
- 标题(h1-h6)
- 段落、换行
- 粗体、斜体、
删除线 - 有序/无序列表
- 任务列表(
- [x]) - 代码块(围栏式 + 语法高亮,180+ 语言)
- 行内代码
- 链接、图片
- 表格
- 引用块
- 水平线
- HTML 内联
9. 快捷键
| 快捷键 | 功能 |
|---|---|
Ctrl + T |
新建标签页 |
Ctrl + W |
关闭当前标签页 |
Ctrl + Tab |
切换到下一个标签页 |
Ctrl + Shift + Tab |
切换到上一个标签页 |
Ctrl + O |
打开文件 |
Ctrl + S |
保存文件 |
Ctrl + Shift + S |
另存为 |
Ctrl + 1 |
编辑 + 预览(分屏) |
Ctrl + 2 |
纯编辑模式 |
Ctrl + 3 |
纯预览模式 |
Ctrl + F |
搜索 |
Ctrl + H |
搜索并替换 |
Enter / Shift+Enter |
下一个 / 上一个匹配 |
Alt + C |
切换区分大小写 |
Alt + R |
切换正则表达式 |
Ctrl + Shift + G |
替换当前匹配 |
Ctrl + Shift + H |
全部替换 |
Esc |
关闭搜索栏 |
10. 构建与发布
使用 electron-builder 打包:
- 输出格式:NSIS 安装包(.exe)
- 目标平台:Windows x64
- 应用图标:assets/icon.ico
- 文件关联:
.md/.markdown/.txt - 支持自定义安装目录、桌面/开始菜单快捷方式
- 便携版:
npm run build:portable
详见 DEVSETUP.md。