# 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 核心功能 1. **文件打开** - 工具栏 → 打开按钮(支持 .md / .txt / .markdown) - 拖拽文件到窗口打开 - 支持 Windows 文件关联(双击 .md 文件打开) - 支持命令行参数传入文件路径 2. **文件保存** - Ctrl+S 快捷键保存 - 工具栏 → 保存按钮 - Ctrl+Shift+S 另存为 3. **实时预览** - 左侧编辑器 + 右侧预览(默认分屏模式) - 编辑 150ms 防抖后更新预览 - 基于 DOM 位置映射的滚动同步 4. **视图模式** - 编辑+预览(Split View)— Ctrl+1 - 纯编辑模式 — Ctrl+2 - 纯预览模式 — Ctrl+3 - 记忆上次使用的视图模式(localStorage) 5. **文件修改检测** - 主进程通过 `fs.watch` 监听当前打开文件 - 外部修改时显示黄色提示横幅 - 支持「重新加载」或「忽略」 6. **未保存提醒** - 关闭窗口时检测未保存修改 - 弹出确认对话框,防止误操作 - 主进程 5 秒超时兜底,防止渲染进程无响应时窗口卡死 7. **暗色主题** - 工具栏右侧月亮/太阳图标切换 - CSS 变量驱动,一键切换整套配色 - 主题偏好持久化(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 ─ □ ✕ │ ├──────────────────────────────────────────────────────────┤ │ 📁 打开 │ 💾 保存 │ ⬜ 分屏 │ ✏️ 编辑 │ 👁 预览 │ 🌙 │ ├──────────────────────────────────────────────────────────┤ │ ⚠️ 文件已被外部程序修改 [重新加载] [忽略] │ ├────────────────────┬─────────────────────────────────────┤ │ │ │ │ 1 # Title │ Title │ │ 2 │ ─────── │ │ 3 content... │ content... │ │ │ │ │ │ │ │ │ │ ├────────────────────┴─────────────────────────────────────┤ │ 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 }` | 重新加载当前文件 | | `window:forceClose` | 无 | 无 | 强制关闭窗口(跳过未保存检查) | ### 5.2 主进程 → 渲染进程(send) | 通道 | 数据 | 说明 | |------|------|------| | `file:opened` | `{ filePath, content }` | 文件已打开 | | `file:externallyModified` | `filePath` | 文件被外部修改 | | `menu:save` | 无 | 菜单触发保存 | | `menu:saveAs` | 无 | 菜单触发另存为 | | `menu:viewMode` | `mode` | 菜单切换视图模式 | | `window:confirmClose` | 无 | 请求确认关闭 | | `window:closing` | 无 | 窗口即将关闭 | ## 6. 数据持久化 通过 `localStorage` 存储用户偏好,key 为 `marklite-settings`: ```json { "darkMode": false, "viewMode": "split", "splitRatio": 50 } ``` | 字段 | 类型 | 说明 | |------|------|------| | `darkMode` | boolean | 暗色主题开关 | | `viewMode` | string | 视图模式:`split` / `editor` / `preview` | | `splitRatio` | number | 分屏比例(20~80) | ## 7. Markdown 渲染支持 支持标准 Markdown 和 GFM(GitHub Flavored Markdown): - 标题(h1-h6) - 段落、换行 - **粗体**、*斜体*、~~删除线~~ - 有序/无序列表 - 任务列表(`- [x]`) - 代码块(围栏式 + 语法高亮,180+ 语言) - 行内代码 - 链接、图片 - 表格 - 引用块 - 水平线 - HTML 内联 ## 8. 快捷键 | 快捷键 | 功能 | |:-------|:-----| | `Ctrl + O` | 打开文件 | | `Ctrl + S` | 保存文件 | | `Ctrl + Shift + S` | 另存为 | | `Ctrl + 1` | 编辑 + 预览(分屏) | | `Ctrl + 2` | 纯编辑模式 | | `Ctrl + 3` | 纯预览模式 | | `F12` | 开发者工具 | | `Ctrl + R` | 重新加载 | ## 9. 构建与发布 使用 `electron-builder` 打包: - 输出格式:NSIS 安装包(.exe) - 目标平台:Windows x64 - 应用图标:assets/icon.ico - 文件关联:`.md` / `.markdown` / `.txt` - 支持自定义安装目录、桌面/开始菜单快捷方式 - 便携版:`npm run build:portable` 详见 [DEVSETUP.md](DEVSETUP.md)。