release: v0.4.0 — MetonaEditor 集成与架构重构
feat(editor): 将 Milkdown/ProseMirror 替换为 @metona-team/metona-editor v0.1.3 - 三模式视图 (edit/split/preview) 由编辑器内置工具栏切换 - searchReplace + imagePaste 预设插件 - unified/rehype 渲染管线通过 render 钩子集成 - 主题双向同步 (应用暗色模式 ↔ 编辑器主题) feat(toast): metona-toast 迁移为 @metona-team/metona-toast v2.0.1 refactor: 删除冗余组件与代码 - 移除 SourceEditor、Preview、SearchReplace、EditorToolbar、useMilkdown - 移除 StatusBar 组件及状态栏扩展架构(编辑器内置底栏替代) - 移除 useSettings、useStatusBarItem、useStatusBarItems、statusBarStore - 移除 EditMode/PreviewMode/SourceMode 图标 refactor(ui): 简化布局 - 工具栏移除模式切换按钮,新增自动保存开关 - useKeyboard 移除 Ctrl+1/2/3/B/I 快捷键 - Editor 三模式统一由 MetonaEditor 容器渲染 chore: 版本号 v0.3.13 → v0.4.0 docs: 全面更新 README/DESIGN/CONTRIBUTING/DEVSETUP
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# MarkLite v0.3.13 — 架构设计文档
|
||||
# MarkLite v0.4.0 — 架构设计文档
|
||||
|
||||
## 1. 项目概述
|
||||
|
||||
MarkLite 是一款轻量级的 Windows 本地 Markdown 编辑器桌面应用程序。基于 Electron + React + TypeScript 构建,采用 Milkdown v7 WYSIWYG 编辑器 + 源码编辑模式、Zustand 状态管理、IndexedDB 持久化、unified/rehype Markdown 渲染管线。
|
||||
MarkLite 是一款轻量级的 Windows 本地 Markdown 编辑器桌面应用程序。基于 Electron + React + TypeScript 构建,采用 MetonaEditor v0.1.3 编辑器(三模式视图 + 插件系统)、Zustand 状态管理、IndexedDB 持久化、unified/rehype Markdown 渲染管线。
|
||||
|
||||
### 1.1 核心原则
|
||||
|
||||
@@ -20,11 +20,12 @@ MarkLite 是一款轻量级的 Windows 本地 Markdown 编辑器桌面应用程
|
||||
| 桌面框架 | Electron | v28 | 跨平台桌面应用框架 |
|
||||
| 前端框架 | React | v18 | 函数组件 + Hooks |
|
||||
| 类型系统 | TypeScript | v5.6 | 全量类型安全 |
|
||||
| 编辑器 | Milkdown | v7 | WYSIWYG 编辑器 + 源码编辑模式 |
|
||||
| 编辑器 | MetonaEditor | v0.1.3 | 零依赖 Markdown 编辑器,三模式视图 + 插件系统 |
|
||||
| 状态管理 | Zustand | v5 | 轻量级状态管理 |
|
||||
| 持久化 | Dexie.js (IndexedDB) | v4 | 标签页状态 / 用户设置 / 最近文件 |
|
||||
| Markdown 解析 | unified / remark / rehype | v11 | 插件化渲染管线 |
|
||||
| Markdown 解析 | unified / remark / rehype | v11 | 插件化渲染管线(作为 MetonaEditor render 钩子) |
|
||||
| 代码高亮 | rehype-highlight | v7 | 基于 highlight.js |
|
||||
| Toast | @metona-team/metona-toast | v2.0.1 | 通知提示组件 |
|
||||
| 构建工具 | electron-vite | v3 | Electron + Vite,HMR 热更新 |
|
||||
| 打包工具 | electron-builder | v25 | Windows NSIS 安装包 |
|
||||
| 样式 | CSS Variables | — | 主题驱动,亮色/暗色 |
|
||||
@@ -50,20 +51,19 @@ MarkLite 是一款轻量级的 Windows 本地 Markdown 编辑器桌面应用程
|
||||
┌───────────────────────▼──────────────────────────────────────┐
|
||||
│ Renderer Process (src/renderer/) React 18 │
|
||||
│ │
|
||||
│ components/ (23) Toolbar · TabBar · Editor · EditorToolbar │
|
||||
│ SourceEditor · Preview · Sidebar · FileTree│
|
||||
│ OutlinePanel · StatusBar · WelcomeScreen │
|
||||
│ Toast · ConfirmDialog · ModifiedBanner │
|
||||
│ SearchReplace · DropOverlay · ErrorBoundary│
|
||||
│ AboutDialog · LoadingSpinner · Icons │
|
||||
│ components/ Toolbar · TabBar · Editor · Sidebar │
|
||||
│ FileTree · OutlinePanel · WelcomeScreen │
|
||||
│ ConfirmDialog · ModifiedBanner │
|
||||
│ DropOverlay · ErrorBoundary · AboutDialog│
|
||||
│ LoadingSpinner · Icons │
|
||||
│ │
|
||||
│ stores/ (5) tabStore · editorStore · sidebarStore │
|
||||
│ statusBarStore · autoSaveStore │
|
||||
│ hooks/ (19) useTheme · useSettings · useSettingsInit │
|
||||
│ useKeyboard · useDragDrop · useFileWatch │
|
||||
│ useAutoSave · useIpcListeners ... │
|
||||
│ lib/ (4) markdown · fileUtils · errorHandler │
|
||||
│ constants │
|
||||
│ stores/ (4) tabStore · editorStore · sidebarStore │
|
||||
│ autoSaveStore │
|
||||
│ hooks/ (15) useTheme · useSettingsInit · useKeyboard │
|
||||
│ useDragDrop · useFileWatch · useAutoSave │
|
||||
│ useIpcListeners · useFileOperations ... │
|
||||
│ lib/ (4) markdown · fileUtils · errorHandler │
|
||||
│ toast · constants │
|
||||
│ db/ (4) schema · tabRepository · settingsRepo │
|
||||
│ recentFilesRepository │
|
||||
│ types/ (5) tab · file · settings · ipc · index │
|
||||
@@ -97,25 +97,18 @@ MarkLite 是一款轻量级的 Windows 本地 Markdown 编辑器桌面应用程
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ App.tsx (根组件) │
|
||||
├─────────┬──────────┬──────────┬──────────┬──────────────┤
|
||||
│Toolbar │ TabBar │ Sidebar │ Editor │ Preview │
|
||||
│ │ │ │ (CM6) │ │
|
||||
├─────────┴──────────┴──────────┴──────────┴──────────────┤
|
||||
├─────────┬──────────┬──────────┬──────────────────────────┤
|
||||
│Toolbar │ TabBar │ Sidebar │ Editor (MetonaEditor) │
|
||||
├─────────┴──────────┴──────────┴──────────────────────────┤
|
||||
│ Zustand Stores │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
|
||||
│ │ tabStore │ │editorStore│ │sidebarStore│ │statusBarStore│ │
|
||||
│ │ - tabs │ │- viewMode│ │- tree │ │- items │ │
|
||||
│ │- activeId│ │- darkMode│ │- expanded │ │ │ │
|
||||
│ │ tabStore │ │editorStore│ │sidebarStore│ │autoSaveStore│ │
|
||||
│ │ - tabs │ │- viewMode│ │- tree │ │- isSaving │ │
|
||||
│ │- activeId│ │- darkMode│ │- expanded │ │- enabled │ │
|
||||
│ │ - mru │ │- extMod │ │- rootPath │ │ │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └─────┬──────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ┌────▼────────────▼────────────▼──────────────▼──────┐ │
|
||||
│ │ ┌──────────────┐ │ │
|
||||
│ │ │autoSaveStore │ │ │
|
||||
│ │ │- isAutoSaving│ │ │
|
||||
│ │ └──────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ ┌────▼────────────▼────────────▼────────────────────┐ │
|
||||
│ │ IndexedDB (Dexie.js) │ │
|
||||
│ │ tabSnapshots │ settings │ recentFiles │ activeTab │ │
|
||||
│ └───────────────────────────────────────────────────┘ │
|
||||
@@ -137,7 +130,7 @@ interface TabState {
|
||||
setModified(tabId, modified) // 设置修改状态
|
||||
getActiveTab() // 获取当前标签
|
||||
updateTabScroll(tabId, scroll) // 更新滚动/光标位置
|
||||
saveToDB() // 保存到 IndexedDB
|
||||
saveToDB() // 保存到 IndexedDB(防抖 500ms)
|
||||
loadFromDB() // 从 IndexedDB 加载
|
||||
}
|
||||
```
|
||||
@@ -151,6 +144,10 @@ interface EditorState {
|
||||
externallyModified: { filePath: string } | null // 外部修改检测状态
|
||||
loadingStates: Record<string, boolean> // 全局加载状态
|
||||
}
|
||||
|
||||
// 模块级 getter — 供 Sidebar/OutlinePanel 访问 MetonaEditor 实例
|
||||
function getMetonaEditor(): MarkdownEditor | null
|
||||
function setMetonaEditorGetter(fn: () => MarkdownEditor | null): void
|
||||
```
|
||||
|
||||
### 3.4 sidebarStore — 侧边栏状态
|
||||
@@ -221,39 +218,78 @@ db.version(1).stores({
|
||||
| `window:confirmClose` | 无 | 请求确认关闭 |
|
||||
| `sidebar:dirChanged` | 无 | 目录结构变化 |
|
||||
|
||||
## 6. 编辑器架构 — Milkdown v7 (WYSIWYG) + SourceEditor (textarea)
|
||||
## 6. 编辑器架构 — MetonaEditor v0.1.3
|
||||
|
||||
### 6.1 双编辑模式
|
||||
### 6.1 三模式视图
|
||||
|
||||
- **编辑模式 (Milkdown)**:基于 ProseMirror 的 WYSIWYG Markdown 编辑器,支持格式化工具栏(粗体/斜体/删除线/标题/列表/引用/代码块/链接/图片/分割线)、搜索替换面板(含正则支持)、自动配对括号/引号、undo/redo
|
||||
- **源码模式 (SourceEditor)**:原生 textarea 控制 Markdown 原文,支持 Tab 缩进、Ctrl+B/I 快捷键
|
||||
- **编辑模式 (edit)**:纯文本编辑器,显示 Markdown 源码
|
||||
- **分屏模式 (split)**:左侧编辑、右侧实时预览,同步滚动
|
||||
- **预览模式 (preview)**:仅显示渲染后的 HTML
|
||||
|
||||
两种模式共享同一 tabStore 数据源,可随时切换。
|
||||
MetonaEditor 内置模式切换工具栏,与应用层的 viewMode store 双向同步,切换时自动持久化到 IndexedDB。
|
||||
|
||||
### 6.1.1 主题切换
|
||||
### 6.2 内置功能
|
||||
|
||||
Milkdown 编辑器通过 CSS class(`milkdown-dark`)切换暗色主题,无需销毁重建 EditorView,
|
||||
切换标签时保持光标位置和选区。
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 格式化工具栏 | bold / italic / strikethrough / underline / code / h1-h3 / quote / ul / ol / indent / outdent / link / image / table / hr |
|
||||
| 搜索替换 | Ctrl+F / Ctrl+H,支持正则、大小写敏感 |
|
||||
| 历史栈 | undo / redo,防抖合并,可配置上限 |
|
||||
| 主题 | light / dark / auto / warm,CSS 变量驱动 |
|
||||
| 国际化 | zh-CN / en-US 完整翻译 |
|
||||
| 全屏模式 | 编辑器全屏展示 |
|
||||
|
||||
### 6.2 插件体系
|
||||
### 6.3 插件体系
|
||||
|
||||
通过 `plugins` 配置数组安装 MetonaEditor 预设插件:
|
||||
|
||||
| 插件 | 说明 |
|
||||
|------|------|
|
||||
| commonmark | 基础 Markdown 语法 |
|
||||
| gfm | GitHub Flavored Markdown(表格/任务列表/删除线等) |
|
||||
| history | undo/redo |
|
||||
| listener | 内容变更监听 |
|
||||
| indent | Tab 缩进 |
|
||||
| trailing | 尾随换行 |
|
||||
| clipboard | 剪贴板增强 |
|
||||
| searchPlugin (自研) | 搜索高亮装饰 |
|
||||
| autoPairPlugin (自研) | 自动配对括号/引号 |
|
||||
| searchReplace | Ctrl+F 查找、Ctrl+H 替换面板 |
|
||||
| imagePaste | Ctrl+V 粘贴剪贴板图片,自动转 base64 |
|
||||
|
||||
### 6.3 滚动与选区持久化
|
||||
> 注:autoSave 插件仅支持 localStorage,而 MarkLite 需要文件系统保存(Electron IPC),因此使用自定义 useAutoSave hook。
|
||||
|
||||
切换标签时自动保存/恢复:
|
||||
- 滚动位置 (`scrollTop`)
|
||||
- 光标选区 (`selectionStart`, `selectionEnd`)
|
||||
### 6.4 渲染管线集成
|
||||
|
||||
通过 MetonaEditor 的 `render` 钩子接入 unified/rehype 管线,实现:
|
||||
|
||||
- **相对路径图片解析**:将相对路径转换为 `file://` 绝对路径
|
||||
- **XSS 防护**:rehype-sanitize 过滤危险标签
|
||||
- **代码高亮**:rehype-highlight 语法高亮
|
||||
- **处理器缓存**:LRU 缓存(最多 20 个),按文件路径分桶
|
||||
|
||||
```
|
||||
Markdown 源码
|
||||
│
|
||||
▼
|
||||
unified 管线(renderMarkdownSync)
|
||||
├── remark-parse 解析为 MDAST
|
||||
├── remark-gfm GFM 扩展
|
||||
├── remark-rehype 转换为 HAST
|
||||
├── rehype-raw 解析内联 HTML
|
||||
├── rehype-sanitize 安全过滤
|
||||
├── rehype-fixImages 相对路径 → file://
|
||||
├── rehype-highlight 代码高亮
|
||||
└── rehype-stringify 序列化为 HTML
|
||||
│
|
||||
▼
|
||||
MetonaEditor 预览区渲染
|
||||
```
|
||||
|
||||
### 6.5 主题切换
|
||||
|
||||
MetonaEditor 的 CSS 样式通过 wrapper 元素上的 inline `--md-*` CSS 变量驱动。主题切换流程:
|
||||
|
||||
1. `MeEditor.setTheme(dark/light)` — 更新 documentElement 全局变量 + localStorage
|
||||
2. 手动覆写 `.me-wrapper` 上的 inline CSS 变量(`style.setProperty`)
|
||||
3. 双向同步:应用工具栏暗色按钮 ⇄ 编辑器主题
|
||||
|
||||
### 6.6 内容同步
|
||||
|
||||
- **编辑 → 存储**:`onChange` 回调 → `updateTabContent` + `setModified`
|
||||
- **标签切换**:`setValue(content, { silent: true })` 静默更新,避免重复触发 onChange
|
||||
- **滚动持久化**:切换标签时通过 DOM 查询 `textarea` / `.me-preview` 保存/恢复滚动位置
|
||||
|
||||
## 7. Markdown 渲染管线
|
||||
|
||||
@@ -285,7 +321,7 @@ rehype-highlight 代码语法高亮
|
||||
rehype-stringify 序列化为 HTML
|
||||
│
|
||||
▼
|
||||
dangerouslySetInnerHTML 渲染到 DOM
|
||||
Renderer (MetonaEditor preview / Preview component)
|
||||
```
|
||||
|
||||
## 8. UI 设计
|
||||
@@ -318,18 +354,21 @@ dangerouslySetInnerHTML 渲染到 DOM
|
||||
┌──────────────────────────────────────────────────────────────────────────┐
|
||||
│ MarkLite - filename.md ─ □ ✕ │
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ 📁 打开 │ 💾 保存 │ ✏️ 编辑 │ 👁 预览 │ 🌙 🔗 ℹ️ │
|
||||
│ 📁 打开 │ 💾 保存 │ 自动 │ 🌙 🌐 ℹ️ │
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ [file1.md] [file2.md] [未命名] [+] │
|
||||
├──────────┬─────────────────────────────────────────────────────────────┤
|
||||
│ 资源管理器 │ │
|
||||
│ ▼ project │ 1 # Title │ Title │
|
||||
│ 📁 src │ 2 │ ─────── │
|
||||
│ 📄 file1│ 3 content... │ content... │
|
||||
│ 📄 file2│ │ │
|
||||
├──────────┴─────────────────────────────────────────────────────────────┤
|
||||
│ filename.md │ UTF-8 │ Markdown │
|
||||
└────────────────────────────────────────────────────────────────────────┘
|
||||
├──────────┬───────────────────────────────────────────────────────────────┤
|
||||
│ 资源管理器 │ │
|
||||
│ ▼ project │ ┌─────────────────────────────────────────────┐ │
|
||||
│ 📁 src │ │ B I S U </> │ H1 H2 H3 │ " 1. 2. ≡ ⇥ ⇤ │ │ │
|
||||
│ 📄 file1│ │ 🔗 🖼 ⊞ — │ ↶ ↷ │ 📝 ⇔ 👁 ⊞ │ │ │
|
||||
│ 📄 file2│ ├─────────────────────────────────────────────┤ │
|
||||
│ │ │ # Title │ Title │ │
|
||||
│ 文档大纲 │ │ │ ─────── │ │
|
||||
│ · Title │ │ content... │ content... │ │
|
||||
├──────────┴──┴─────────────────────────────────────────────┴──────────────┤
|
||||
│ (MetonaEditor 底栏: 字数/行数/阅读时间) │
|
||||
└──────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 9. 构建与发布
|
||||
@@ -365,7 +404,8 @@ npm run build:portable # 便携版(免安装)
|
||||
| zustand | ^5.0 | 状态管理 |
|
||||
| dexie | ^4.0 | IndexedDB 封装 |
|
||||
| nanoid | ^5.0 | 唯一 ID 生成 |
|
||||
| @milkdown/* | 7.21.1 | WYSIWYG Markdown 编辑器(基于 ProseMirror) |
|
||||
| @metona-team/metona-editor | ^0.1.3 | Markdown 编辑器(零依赖) |
|
||||
| @metona-team/metona-toast | ^2.0.1 | Toast 通知组件 |
|
||||
| unified / remark / rehype | ^11.0 | Markdown 渲染管线 |
|
||||
| rehype-highlight | ^7.0 | 代码语法高亮 |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user