refactor: v2.0 全量重构 — TypeScript + React + Zustand + IndexedDB
技术栈升级: - JavaScript → TypeScript 5.6(全量类型安全) - 原生 DOM → React 18(函数组件 + Hooks) - 全局变量 → Zustand 5(轻量状态管理) - localStorage → IndexedDB / Dexie.js 4(大容量、异步、索引) - marked.js → unified / remark / rehype(插件化渲染管线) - 无打包 → electron-vite 3(HMR 热更新) - 纯 CSS → CSS Variables + CSS Modules 新增功能: - 标签页状态 IndexedDB 持久化(关闭后可恢复) - 最近打开文件列表 - 大文件虚拟化行号(>2000 行) - 搜索高亮二分查找优化 O(log N) - rehype-sanitize HTML 安全过滤 文件结构: - 7 个源文件 → 51 个模块化文件 - src/main/ 主进程(6 文件) - src/preload/ 预加载(1 文件) - src/renderer/ 渲染进程(42 文件:组件/hooks/stores/lib/db/types/styles) - src/shared/ 共享类型(2 文件) 构建验证: - TypeScript 检查零错误 - electron-vite build 成功 - 产物:main 15kB + preload 2kB + renderer 1.5MB
This commit is contained in:
@@ -11,13 +11,15 @@
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/Platform-Windows%20x64-blue?style=flat-square&logo=windows" alt="Platform">
|
||||
<img src="https://img.shields.io/badge/Electron-28-47848F?style=flat-square&logo=electron" alt="Electron">
|
||||
<img src="https://img.shields.io/badge/TypeScript-5.6-3178C6?style=flat-square&logo=typescript" alt="TypeScript">
|
||||
<img src="https://img.shields.io/badge/React-18-61DAFB?style=flat-square&logo=react" alt="React">
|
||||
<img src="https://img.shields.io/badge/License-MIT-green?style=flat-square" alt="License">
|
||||
<img src="https://img.shields.io/badge/Version-1.2.0-orange?style=flat-square" alt="Version">
|
||||
<img src="https://img.shields.io/badge/Version-2.0.0-orange?style=flat-square" alt="Version">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
基于 Electron 构建,开箱即用的 Markdown 桌面编辑器。<br>
|
||||
多标签页 · 实时预览 · 代码高亮 · 暗色主题 · 拖拽打开 · 搜索替换 · 文件树。
|
||||
基于 Electron + React + TypeScript 构建的现代化 Markdown 桌面编辑器。<br>
|
||||
多标签页 · 实时预览 · 代码高亮 · 暗色主题 · 拖拽打开 · 搜索替换 · 文件树 · IndexedDB 持久化。
|
||||
</p>
|
||||
|
||||
---
|
||||
@@ -26,20 +28,21 @@
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 📑 **多标签页** | 同时打开多个文件,Ctrl+T 新建、Ctrl+W 关闭、Ctrl+Tab 切换 |
|
||||
| 📂 **文件打开** | 按钮打开 / 拖拽打开 / 文件关联(双击 .md) |
|
||||
| ✏️ **实时编辑** | 左侧编辑器,支持 Tab 缩进、行号显示、光标位置 |
|
||||
| 👁 **实时预览** | 右侧预览面板,编辑即渲染,滚动同步 |
|
||||
| 🔤 **代码高亮** | 基于 highlight.js,支持 180+ 种编程语言语法高亮 |
|
||||
| 📑 **多标签页** | 同时打开多个文件,Ctrl+T 新建、Ctrl+W 关闭、Ctrl+Tab MRU 切换 |
|
||||
| 📂 **文件打开** | 按钮打开 / 拖拽打开 / 文件关联(双击 .md) / 命令行参数 |
|
||||
| ✏️ **实时编辑** | 左侧编辑器,支持 Tab 缩进、行号显示、光标位置、大文件虚拟化行号 |
|
||||
| 👁 **实时预览** | 右侧预览面板,基于 unified/rehype 管线渲染,编辑即更新 |
|
||||
| 🔤 **代码高亮** | 基于 rehype-highlight,支持 180+ 种编程语言语法高亮 |
|
||||
| 🎨 **三种视图** | 分屏模式 / 纯编辑 / 纯预览,自由切换 |
|
||||
| 📐 **分屏调节** | 拖拽中间分隔条,自由调整编辑区与预览区比例 |
|
||||
| 🌙 **暗色主题** | 一键切换亮色/暗色主题,偏好自动记忆 |
|
||||
| 🔔 **文件监听** | 外部修改文件时自动提示,支持重新加载 |
|
||||
| 💾 **文件保存** | 保存 / 另存为,支持 .md 和 .txt 格式 |
|
||||
| 🌙 **暗色主题** | 一键切换亮色/暗色主题,偏好自动记忆(IndexedDB) |
|
||||
| 🔔 **文件监听** | 外部修改文件时自动提示,支持重新加载或忽略 |
|
||||
| 💾 **文件保存** | 保存 / 另存为,支持 .md / .markdown / .txt 格式 |
|
||||
| 🔍 **搜索替换** | Ctrl+F 搜索、Ctrl+H 替换,支持高亮匹配、大小写、正则表达式 |
|
||||
| 📁 **文件树** | 侧边栏浏览项目目录,点击打开文件,自动刷新 |
|
||||
| 📁 **文件树** | 侧边栏浏览项目目录,点击打开文件,目录变化自动刷新 |
|
||||
| 💾 **状态持久化** | 标签页状态、用户设置通过 IndexedDB 持久化,关闭后可恢复 |
|
||||
| ⌨️ **快捷键** | 完整的键盘快捷键支持,操作高效 |
|
||||
| 📦 **NSIS 安装包** | 一键打包为 Windows exe 安装程序 |
|
||||
| 📦 **NSIS 安装包** | 一键打包为 Windows exe 安装程序 / 便携版 |
|
||||
|
||||
## 📸 界面预览
|
||||
|
||||
@@ -49,7 +52,7 @@
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ 📁 打开 │ 💾 保存 │ ⬜ 分屏 │ ✏️ 编辑 │ 👁 预览 │ 🌙 │
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ [README.md] [DESIGN.md] [main.js] [+] │
|
||||
│ [README.md] [DESIGN.md] [main.ts] [+] │
|
||||
├──────────┬─────────────────────────┬─────────────────────────────────────┤
|
||||
│ 资源管理器│ │ │
|
||||
│ ▼ MarkLite│ 🔍 查找... 3/12 │ MarkLite │
|
||||
@@ -71,8 +74,8 @@
|
||||
|
||||
### 环境要求
|
||||
|
||||
- **Node.js** >= 16.x
|
||||
- **npm** >= 8.x
|
||||
- **Node.js** >= 18.x
|
||||
- **npm** >= 9.x
|
||||
- **Windows** 10/11 x64
|
||||
|
||||
### 安装与运行
|
||||
@@ -85,8 +88,8 @@ cd MarkLite
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 启动应用
|
||||
npm start
|
||||
# 启动开发模式(带 HMR 热更新)
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 打包为 exe 安装包
|
||||
@@ -101,13 +104,23 @@ npm run build:portable
|
||||
|
||||
打包完成后,安装包位于 `dist/` 目录。详见 [DEVSETUP.md](DEVSETUP.md)。
|
||||
|
||||
### 其他命令
|
||||
|
||||
```bash
|
||||
# TypeScript 类型检查
|
||||
npm run typecheck
|
||||
|
||||
# ESLint 代码检查
|
||||
npm run lint
|
||||
```
|
||||
|
||||
## ⌨️ 快捷键
|
||||
|
||||
| 快捷键 | 功能 |
|
||||
|:-------|:-----|
|
||||
| `Ctrl + T` | 新建标签页 |
|
||||
| `Ctrl + W` | 关闭当前标签页 |
|
||||
| `Ctrl + Tab` | 切换到下一个标签页 |
|
||||
| `Ctrl + Tab` | 切换到下一个标签页(MRU 顺序) |
|
||||
| `Ctrl + Shift + Tab` | 切换到上一个标签页 |
|
||||
| `Ctrl + O` | 打开文件 |
|
||||
| `Ctrl + S` | 保存文件 |
|
||||
@@ -129,57 +142,145 @@ npm run build:portable
|
||||
| 组件 | 技术 | 说明 |
|
||||
|:-----|:-----|:-----|
|
||||
| 桌面框架 | [Electron](https://www.electronjs.org/) v28 | 跨平台桌面应用框架 |
|
||||
| Markdown 解析 | [marked.js](https://marked.js.org/) v12 | 高性能 Markdown 解析器 |
|
||||
| 代码高亮 | [highlight.js](https://highlightjs.org/) v11 | 代码语法高亮引擎 |
|
||||
| 前端框架 | [React](https://react.dev/) v18 | 函数组件 + Hooks |
|
||||
| 类型系统 | [TypeScript](https://www.typescriptlang.org/) v5.6 | 全量类型安全 |
|
||||
| 状态管理 | [Zustand](https://zustand-demo.pmnd.rs/) v5 | 轻量级状态管理 |
|
||||
| 持久化 | [Dexie.js](https://dexie.org/) v4 (IndexedDB) | 标签页状态 & 用户设置持久化 |
|
||||
| Markdown 解析 | [unified](https://unifiedjs.com/) / [remark](https://remark.js.org/) / [rehype](https://rehype.js.org/) | 插件化 Markdown 渲染管线 |
|
||||
| 代码高亮 | [rehype-highlight](https://github.com/rehypejs/rehype-highlight) | 基于 highlight.js 的语法高亮 |
|
||||
| 构建工具 | [electron-vite](https://electron-vite.org/) v3 | Electron + Vite 集成,HMR 热更新 |
|
||||
| 打包工具 | [electron-builder](https://www.electron.build/) | 生成 exe 安装包 |
|
||||
| 前端 | HTML + CSS + JavaScript | 原生技术,零框架依赖 |
|
||||
| 样式 | CSS Variables + CSS Modules | 主题驱动,样式隔离 |
|
||||
|
||||
## 📁 项目结构
|
||||
|
||||
```
|
||||
MarkLite/
|
||||
├── package.json # 项目配置 & electron-builder 打包配置
|
||||
├── main.js # Electron 主进程(窗口、文件系统、IPC)
|
||||
├── preload.js # 预加载脚本(安全 IPC 桥接)
|
||||
├── renderer/
|
||||
│ ├── index.html # 主页面结构
|
||||
│ ├── style.css # UI 样式(亮色/暗色主题)
|
||||
│ └── renderer.js # 渲染进程逻辑(标签页、编辑、预览)
|
||||
├── lib/
|
||||
│ ├── marked.min.js # marked.js(本地离线)
|
||||
│ ├── highlight.min.js # highlight.js(本地离线)
|
||||
│ └── highlight-github.css # GitHub 风格代码主题
|
||||
├── package.json # 项目配置 & 依赖 & electron-builder 打包配置
|
||||
├── tsconfig.json # TypeScript 配置
|
||||
├── tsconfig.node.json # Node 端 TypeScript 配置
|
||||
├── electron.vite.config.ts # electron-vite 构建配置
|
||||
├── .eslintrc.cjs # ESLint + TypeScript 规则
|
||||
│
|
||||
├── src/
|
||||
│ ├── main/ # ===== 主进程 (Node.js) =====
|
||||
│ │ ├── index.ts # 入口:窗口创建、app 生命周期、单实例锁
|
||||
│ │ ├── ipc-handlers.ts # 所有 ipcMain.handle 注册
|
||||
│ │ ├── file-system.ts # 文件读写、目录树构建、BOM 剥离
|
||||
│ │ ├── file-watcher.ts # fs.watch 封装(单文件 + 目录监听)
|
||||
│ │ ├── window-manager.ts # 窗口创建、关闭拦截、单实例锁
|
||||
│ │ └── ipc-channels.ts # IPC 通道名常量
|
||||
│ │
|
||||
│ ├── preload/ # ===== 预加载脚本 =====
|
||||
│ │ └── index.ts # contextBridge 类型安全暴露
|
||||
│ │
|
||||
│ ├── renderer/ # ===== 渲染进程 (React) =====
|
||||
│ │ ├── index.html # 入口 HTML(含 CSP 策略)
|
||||
│ │ ├── main.tsx # React 入口 (createRoot)
|
||||
│ │ ├── App.tsx # 根组件:布局编排、全局事件
|
||||
│ │ │
|
||||
│ │ ├── components/ # ----- UI 组件 -----
|
||||
│ │ │ ├── Toolbar/ # 工具栏(打开、保存、视图切换、暗色主题)
|
||||
│ │ │ ├── TabBar/ # 标签页栏(多标签、关闭、MRU 切换)
|
||||
│ │ │ ├── Editor/ # 编辑器(行号、大文件虚拟化、Tab 缩进)
|
||||
│ │ │ ├── Preview/ # Markdown 预览面板(unified/rehype 渲染)
|
||||
│ │ │ ├── Sidebar/ # 侧边栏文件树(递归、展开折叠、独立文件区)
|
||||
│ │ │ ├── SearchBar/ # 搜索替换栏(高亮、正则、大小写)
|
||||
│ │ │ ├── StatusBar/ # 状态栏(文件名、编码、语言)
|
||||
│ │ │ ├── WelcomeScreen/ # 欢迎屏幕
|
||||
│ │ │ ├── Toast/ # Toast 通知
|
||||
│ │ │ ├── ModifiedBanner/ # 文件外部修改提示横幅
|
||||
│ │ │ └── DropOverlay/ # 拖拽文件覆盖层
|
||||
│ │ │
|
||||
│ │ ├── stores/ # ----- Zustand 状态管理 -----
|
||||
│ │ │ ├── tabStore.ts # 标签页状态(tabs、activeTabId、mruStack)
|
||||
│ │ │ ├── editorStore.ts # 编辑器状态(viewMode、darkMode、splitRatio)
|
||||
│ │ │ ├── sidebarStore.ts # 侧边栏状态(tree、expandedDirs、rootPath)
|
||||
│ │ │ └── searchStore.ts # 搜索替换状态(matches、currentIndex、options)
|
||||
│ │ │
|
||||
│ │ ├── hooks/ # ----- 自定义 Hooks -----
|
||||
│ │ │ ├── useTheme.ts # 暗色/亮色主题(IndexedDB 持久化)
|
||||
│ │ │ ├── useSettings.ts # 用户设置读写
|
||||
│ │ │ ├── useKeyboard.ts # 全局快捷键
|
||||
│ │ │ ├── useDragDrop.ts # 拖拽打开文件
|
||||
│ │ │ ├── useFileWatch.ts # 外部文件修改监听
|
||||
│ │ │ └── useUnsavedWarning.ts # 未保存提醒(Electron + 浏览器兼容)
|
||||
│ │ │
|
||||
│ │ ├── lib/ # ----- 工具库 -----
|
||||
│ │ │ ├── markdown.ts # Markdown 渲染管线(unified → remark → rehype)
|
||||
│ │ │ ├── scrollSync.ts # 滚动同步算法(块级元素 DOM 位置映射)
|
||||
│ │ │ ├── searchEngine.ts # 搜索匹配引擎(普通/正则/大小写/二分查找)
|
||||
│ │ │ ├── fileUtils.ts # 文件大小格式化、扩展名检查
|
||||
│ │ │ └── constants.ts # 常量定义
|
||||
│ │ │
|
||||
│ │ ├── db/ # ----- IndexedDB 持久化层 -----
|
||||
│ │ │ ├── schema.ts # Dexie 数据库定义 + 类型(tabSnapshots/settings/recentFiles)
|
||||
│ │ │ ├── tabRepository.ts # 标签页状态 CRUD
|
||||
│ │ │ ├── settingsRepository.ts # 用户设置 CRUD
|
||||
│ │ │ └── recentFilesRepository.ts # 最近打开文件
|
||||
│ │ │
|
||||
│ │ ├── types/ # ----- TypeScript 类型 -----
|
||||
│ │ │ ├── tab.ts # Tab 接口
|
||||
│ │ │ ├── file.ts # FileNode, DirTree 等
|
||||
│ │ │ ├── settings.ts # Settings 接口 + 默认值
|
||||
│ │ │ ├── search.ts # SearchMatch, SearchOptions
|
||||
│ │ │ ├── ipc.ts # ElectronAPI 接口 + IPC 通道类型映射
|
||||
│ │ │ └── index.ts # 类型统一导出
|
||||
│ │ │
|
||||
│ │ └── styles/ # ----- 全局样式 -----
|
||||
│ │ ├── variables.css # CSS 变量(亮色/暗色主题)
|
||||
│ │ ├── global.css # 全局 reset + 布局 + 组件样式
|
||||
│ │ └── markdown-body.css # Markdown 预览正文样式
|
||||
│ │
|
||||
│ └── shared/ # ===== 主进程/渲染进程共享 =====
|
||||
│ ├── ipc-channels.ts # IPC 通道名常量
|
||||
│ └── types.ts # 共享类型定义
|
||||
│
|
||||
├── lib/ # 第三方离线库(marked.js, highlight.js)
|
||||
├── assets/
|
||||
│ └── icon.ico # 应用图标(多尺寸)
|
||||
├── DESIGN.md # 架构设计文档
|
||||
├── DEVSETUP.md # 开发环境配置指南
|
||||
├── LICENSE # MIT 许可证
|
||||
└── README.md # 项目说明
|
||||
│ └── icon.ico # 应用图标(多尺寸)
|
||||
├── DESIGN.md # 架构设计文档
|
||||
├── DEVSETUP.md # 开发环境配置指南
|
||||
├── REFACTOR-PLAN.md # 重构方案文档
|
||||
├── LICENSE # MIT 许可证
|
||||
└── README.md # 本文件
|
||||
```
|
||||
|
||||
## 🏗️ 架构设计
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ Main Process (main.js) │
|
||||
│ 窗口管理 · 文件系统 · 文件监听 · IPC │
|
||||
│ 目录树读取 · 侧边栏目录监听 │
|
||||
└──────────────┬───────────────────────────┘
|
||||
│ contextBridge (安全隔离)
|
||||
┌──────────────▼───────────────────────────┐
|
||||
│ Preload Script (preload.js) │
|
||||
│ 安全 API 桥接层 │
|
||||
└──────────────┬───────────────────────────┘
|
||||
│
|
||||
┌──────────────▼───────────────────────────┐
|
||||
│ Renderer Process (renderer/) │
|
||||
│ 标签页 · 编辑器 · 预览 · 暗色主题 │
|
||||
│ 搜索替换 · 文件树侧边栏 · 拖拽 · 快捷键 │
|
||||
│ localStorage │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Main Process (src/main/) │
|
||||
│ 窗口管理 · 文件系统 · 文件监听 · IPC · 目录树 · 单实例锁 │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│ contextBridge (安全隔离)
|
||||
┌──────────────────────▼──────────────────────────────────────┐
|
||||
│ Preload Script (src/preload/) │
|
||||
│ 类型安全 API 桥接层 │
|
||||
└──────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
┌──────────────────────▼──────────────────────────────────────┐
|
||||
│ Renderer Process (src/renderer/) — React 18 │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Components (11 个) │ │
|
||||
│ │ Toolbar · TabBar · Editor · Preview · Sidebar │ │
|
||||
│ │ SearchBar · StatusBar · WelcomeScreen · Toast │ │
|
||||
│ │ ModifiedBanner · DropOverlay │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Zustand Stores (4 个) │ │
|
||||
│ │ tabStore · editorStore · sidebarStore · searchStore │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ IndexedDB (Dexie.js) │ │
|
||||
│ │ tabSnapshots · settings · recentFiles │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
> 安全策略:`contextIsolation: true` + `nodeIntegration: false` + CSP,渲染进程无法直接访问 Node.js API。
|
||||
安全策略:contextIsolation: true + nodeIntegration: false + CSP
|
||||
渲染进程无法直接访问 Node.js API
|
||||
```
|
||||
|
||||
## 📝 支持的 Markdown 语法
|
||||
|
||||
@@ -187,9 +288,9 @@ MarkLite/
|
||||
- ✅ **粗体** / *斜体* / ~~删除线~~
|
||||
- ✅ 有序列表 / 无序列表
|
||||
- ✅ 任务列表 `- [x]`
|
||||
- ✅ 代码块(围栏式 + 语法高亮)
|
||||
- ✅ 代码块(围栏式 + 语法高亮,180+ 语言)
|
||||
- ✅ 行内代码
|
||||
- ✅ 链接 / 图片
|
||||
- ✅ 链接 / 图片(支持相对路径)
|
||||
- ✅ 表格
|
||||
- ✅ 引用块
|
||||
- ✅ 水平线
|
||||
|
||||
Reference in New Issue
Block a user