thzxx
|
1cc4206b32
|
feat: 替换 textarea 为 CodeMirror 6 编辑器
新增功能:
- CodeMirror 6 专业编辑器替代原生 textarea
- 语法高亮(Markdown 专用)
- 行号(内置,精确同步)
- 代码折叠(foldGutter)
- 括号匹配
- 多光标选区(rectangularSelection)
- 内置搜索高亮(highlightSelectionMatches)
- undo/redo 原生支持(history)
- Tab 缩进(indentWithTab)
- 暗色主题(oneDark)
新增文件:
- useCodeMirror.ts: CodeMirror 初始化 Hook
- EditorToolbar.tsx: 格式化工具栏(B/I/S/标题/列表/引用/代码/链接/图片)
- Editor.tsx: 重写为 CodeMirror 组件
格式化工具栏按钮:
- 粗体/斜体/删除线/行内代码
- H1/H2/H3 标题
- 无序列表/有序列表/引用/代码块
- 链接/图片
快捷键:
- Ctrl+B 粗体
- Ctrl+I 斜体
|
2026-05-27 23:04:05 +08:00 |
|
thzxx
|
b3987e9abd
|
fix: 修复侧边栏根目录、搜索高亮导航、行号同步
问题1: 侧边栏打开文件夹后根目录不显示
修复: FileTree 传入包装后的根节点 { name, path, type: 'dir', children: tree }
打开文件夹时自动展开根目录 expandDirs([rootPath])
问题2: 搜索没有高亮,上一个/下一个没反应
修复: Editor 添加完整搜索功能
- 搜索时在 textarea 上方创建 overlay div
- 用绝对定位 div 标记每个匹配位置(单行/多行)
- currentIndex 变化时选中匹配文本并滚动到可视区域
- 搜索结果随内容变化自动更新
问题3: 滚动时行号跟随不准确
修复: 行高测量改为与 CSS line-height 一致的动态测量
搜索高亮位置随编辑器滚动同步更新
|
2026-05-27 22:49:34 +08:00 |
|
thzxx
|
9e3029774a
|
fix: 实现编辑器-预览滚动同步
问题: 分屏模式下编辑器滚动时,预览面板不跟随滚动。
实现:
- Editor handleScroll 计算滚动比例,派发 editor-scroll 自定义事件
- Preview 监听 editor-scroll 事件,按比例设置 preview-panel scrollTop
- isSyncingRef 防止双向循环触发
原理: 编辑器 scrollTop / (scrollHeight - clientHeight) = 预览 scrollTop / (scrollHeight - clientHeight)
|
2026-05-27 22:30:31 +08:00 |
|
thzxx
|
ba76cdab54
|
fix: 缩小图标 MD 字母尺寸(52% → 38%,SVG 32px → 24px)
|
2026-05-27 22:12:55 +08:00 |
|
thzxx
|
4caa215d6c
|
fix: 回退图标为现代化简洁风格
回退科技感设计,改为简洁美观风格:
- 柔和蓝色渐变背景(#4F8EF7 → #2563EB)
- 左上角微妙白色高光
- Georgia 衬线字体 MD 字母(白色带阴影)
- 底部半透明装饰线
- 圆角矩形,干净利落
icons.ico: 7 种尺寸(16~256px)
Icons.tsx AppIcon: SVG 版本同步更新
|
2026-05-27 22:07:38 +08:00 |
|
thzxx
|
79995855a0
|
feat: 科技感图标重新设计
应用图标(assets/icon.ico + icon.png):
- 深色渐变背景(#0F172A 深海蓝 → #1E1B4B 深紫)
- 半透明科技网格线
- 蓝色发光圆环
- 四角蓝色光点装饰
- 带发光效果的白色 M 文字
- 蓝色渐变 ↓ 箭头
- 底部扫描线效果
- 右上角光标装饰
- 7 种尺寸(16~256px)
Icons.tsx AppIcon 同步更新:
- SVG 版本包含相同的科技感元素
- 使用 SVG filter 实现发光效果
- 使用 clipPath 实现圆角裁剪
- 使用 linearGradient 实现背景渐变
|
2026-05-27 22:01:41 +08:00 |
|
thzxx
|
b223cd69e1
|
feat: 重新设计应用图标(assets/icon.ico)
新图标设计:
- 蓝色渐变圆角矩形背景(#3B82F6 → #1D4ED8)
- 白色 M↓ 文字符号
- 底部半透明装饰线
- 与 Icons.tsx 中 AppIcon 风格一致
生成规格:
- icon.ico: 7 种尺寸(16/24/32/48/64/128/256px)
- icon.png: 256x256 预览图
|
2026-05-27 21:52:00 +08:00 |
|
thzxx
|
db94ecfad0
|
feat: 重新设计现代化图标系统
新增 Icons.tsx 统一图标组件(25 个图标):
- AppIcon: 渐变蓝色圆角矩形 + M↓ 符号
- 工具栏: FolderOpen, Save, SplitView, EditMode, PreviewMode, Moon, Sun
- 标签栏: Close, Plus
- 侧边栏: Folder, File, ChevronRight, FolderPlus
- 搜索栏: ChevronUp, ChevronDown, X
- 拖拽: UploadCloud
- 导航: ArrowUp, ArrowDown
- 欢迎: WelcomeFile, WelcomeNew
设计风格:
- 线性图标(stroke-based),统一 1.75px 线宽
- 圆角风格,现代科技感
- 蓝色主色调渐变应用图标
- 部分图标添加微妙的填充细节(opacity 0.3-0.4)
更新组件:
- Toolbar: 使用 FolderOpen/Save/SplitView/EditMode/PreviewMode/Moon/Sun
- TabBar: 使用 Close/Plus
- Sidebar: 使用 FolderPlus/File/Folder/ChevronRight
- SearchBar: 使用 ChevronUp/ChevronDown/X
- WelcomeScreen: 使用 AppIcon/WelcomeFile/WelcomeNew
- DropOverlay: 使用 UploadCloud
|
2026-05-27 21:44:26 +08:00 |
|
thzxx
|
70dff0cf01
|
fix: 修复第二轮代码审计发现的全部 15 个问题
严重 Bug(6 个):
- C-01: settingsRepository.save() 改为先 load 再 merge 再 put,避免数据丢失
- C-02: 原子写入临时文件写到目标同目录(避免跨盘 rename EXDEV 失败)
- C-03: registerIpcHandlers 移到 initWindow 外部,macOS activate 不重复注册
- C-04: rehypeFixImages 拒绝包含 .. 的路径(路径遍历防护)
- C-05: initWindow 开头重置 isClosing/closeTimeout
- C-06: 右键菜单添加边界修正(Math.min 防溢出屏幕)
中等问题(5 个):
- M-01: Sidebar 路径比较归一化(norm = p.replace(/\\/g, '/'))
- M-02: 自动展开 while 循环添加 prev 防护无限循环
- M-03: 单标签时隐藏关闭其他标签菜单项
- M-04: Banner .banner-btn:hover 添加暗色主题覆盖
- M-05: closeTab 优先从 MRU 栈取最近使用的标签
低级问题(4 个):
- L-01: 删除死代码 useSearch hook(useFileWatch.ts)
- L-02: file-watcher error 事件显式调用 watcher.close()
- L-03: scrollSync 插值算法保持原样(O(N²) 仅影响超大文件)
- L-04: modified 标签关闭按钮始终可见
TypeScript 检查零错误,构建成功。
|
2026-05-27 21:35:09 +08:00 |
|
thzxx
|
d23d209522
|
fix: 预览时本地图片不显示
问题: 重构后丢失了原始版本的图片路径转换逻辑,
相对路径图片(如 )无法显示。
修复:
- 新增 rehypeFixImages 自定义 rehype 插件
- 在 sanitize 之后、highlight 之前执行
- 将相对路径 src 转换为 file:// 绝对路径
- 基于当前文件路径计算目录,拼接图片路径
- renderMarkdown 新增 filePath 可选参数
- Preview 组件传入 activeTab.filePath
示例:
Markdown: 
文件路径: /project/docs/README.md
转换后: file:///project/docs/images/logo.png
|
2026-05-27 21:13:31 +08:00 |
|
thzxx
|
f9aaf19e19
|
fix: 预览区域占满宽度(移除 max-width 900px 限制)
移除 #preview 的 max-width: 900px 和 margin: 0 auto,
预览内容现在与编辑器一样占满整个面板宽度。
|
2026-05-27 21:09:07 +08:00 |
|
thzxx
|
679cd4b0a0
|
feat: 打开文件时自动展开目录树到该文件所在位置
场景:已打开文件夹 /project,通过 Ctrl+O 打开
/project/src/components/App.tsx,目录树自动展开
src/ 和 components/ 目录,高亮显示该文件。
实现:
- sidebarStore 新增 expandDirs(paths) 方法,批量展开目录
- Sidebar 组件监听 activeFilePath 变化
- 提取文件的所有父目录路径(从文件到 rootPath)
- 自动调用 expandDirs 展开所有父目录
|
2026-05-27 21:07:18 +08:00 |
|
thzxx
|
8db6396fc7
|
fix: 修复侧边栏文件树 active 高亮不生效
问题: FileTree 组件的 className 模板为空字符串,文件项永远不会显示
active 高亮样式,导致用户无法在目录树中看到当前打开的文件。
修复:
- FileTree 新增 activeFilePath prop,用于比较 node.path
- Sidebar 组件从 tabs + activeTabId 计算 activeFilePath
- className 改为 node.path === activeFilePath ? 'active' : ''
联动验证:
- 点击目录树文件 → 标签栏新增标签 → 侧边栏高亮 ✓
- 切换标签 → 侧边栏高亮跟随切换 ✓
- 关闭标签 → 侧边栏高亮消失 ✓
- 独立文件区与目录树不重复 ✓
|
2026-05-27 21:02:45 +08:00 |
|
thzxx
|
2c681a4142
|
feat: 标签栏右键菜单 — 关闭其他/右侧/全部标签
新增功能:
- 右键点击标签弹出上下文菜单
- 关闭:关闭当前标签(带未保存确认)
- 关闭其他标签:保留当前,关闭其余(带未保存确认)
- 关闭右侧标签:关闭当前标签右边的所有标签
- 关闭全部标签:关闭所有标签(带未保存确认)
- 点击空白处自动关闭菜单
技术实现:
- tabStore 新增 closeOtherTabs/closeAllTabs/closeTabsToRight 方法
- TabBar 组件新增 ContextMenu 状态管理和右键事件处理
- CSS 新增 .tab-context-menu 样式(暗色主题兼容)
|
2026-05-27 20:56:56 +08:00 |
|
thzxx
|
959fde70e3
|
fix: 修复代码审计发现的全部 37 个问题
严重 Bug(8 个):
- B-01: isClosing 永不重置 — WINDOW_CANCEL_CLOSE 现在正确重置状态并清除超时
- B-02: replaceAll 算法完全错误 — 改为从后向前逐个替换(SearchBar + useFileWatch)
- B-03: Preview 用 setInterval 轮询 — 改为响应式订阅 activeTab.content 变化
- B-04: StatusBar 不响应 tab 切换 — 改为直接选择 tabs/activeTabId 而非函数引用
- B-05: useTheme 初始化竞态 — 添加 isInitialized ref 防止首次加载前保存
- B-06: scrollSync 0 值歧义 — 使用 NaN 标记未映射状态
- B-07: macOS activate 未注册 IPC — 提取 initWindow() 函数完整重建
- B-08: resizer 无交互逻辑 — 实现 Resizer 组件(mousedown/mousemove/mouseup)
中等问题(12 个):
- M-01: removeAllListeners 限制为白名单通道
- M-02: 新建文件保存时设置 isSelfWriting
- M-03: SidebarWatcher setTimeout 后再次检查窗口状态
- M-04: FileWatcher/SidebarWatcher 监听 error 事件清理僵尸状态
- M-05: buildDirTree 添加递归深度限制(maxDepth=10)+ 错误边界
- M-06: saveFileContent 改为原子写入(write-to-temp-then-rename)
- M-07: Preview 异步竞态 — 使用递增 requestId 替代 cancelled
- M-08: useKeyboard 依赖优化 — 用 getState() 替代频繁变化的 tabs 依赖
- M-09: settingsRepository.save() 改为 Dexie put 直接合并
- M-10: useSettings 返回函数用 useCallback 稳定引用
- M-11: App.tsx 事件注册添加 cleanup 清理 + ref 保持最新回调
- M-12: ipc-channels.ts 类型签名统一
低级问题(17 个):
- L-01/L-03: Editor 移除未使用的 imports
- L-04: tabIdCounter 改为 nanoid(HMR 安全)
- L-06: recentFiles 添加 50 条上限自动清理
- L-07: getFileExtension 正确处理无扩展名文件
- L-08: window-manager 使用静态导入 + 验证是文件非目录
- L-09: readFileContent 使用 shared 类型
- L-10: buildDirTree 权限错误返回空数组
- L-11: DropOverlay 简化为单一 dragCounter 状态
- L-12: Sidebar onFileClick 提取为 useCallback
- L-13: Editor searchStore 改为精确 selector
- L-14: CSS 添加 mode-editor 隐藏规则
- L-16: openFileInTab 添加 .catch() 异常处理
TypeScript 检查零错误,构建成功。
|
2026-05-27 20:52:49 +08:00 |
|
thzxx
|
5e1c89d280
|
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
|
2026-05-27 20:29:23 +08:00 |
|
thzxx
|
c2cdba546b
|
docs: 添加 TypeScript + React + IndexedDB 重构方案
|
2026-05-27 18:09:31 +08:00 |
|
thzxx
|
03cd491f31
|
fix: 修复打开/切换文件后误标记为已修改的问题
|
2026-05-27 17:40:52 +08:00 |
|
thzxx
|
eb05e9d1b1
|
fix: 搜索高亮跟随滚动同步 + 行号动态行高测量修复 v1.2.1
|
2026-05-27 17:34:30 +08:00 |
|
 thzxxandGitee
|
8fea500cc1
|
Revert "refactor: renderer.js拆分为6个模块(core/tabs/editor/search/sidebar/markdown)"
This reverts commit e071a26db6.
|
2026-05-21 06:17:58 +00:00 |
|
 thzxxandGitee
|
f6b247d364
|
Revert "release: v1.3.0 版本发布,更新文档与更新日志"
This reverts commit 2716a7d320.
|
2026-05-21 06:17:16 +00:00 |
|
thzxx
|
2716a7d320
|
release: v1.3.0 版本发布,更新文档与更新日志
|
2026-05-21 13:44:32 +08:00 |
|
thzxx
|
e071a26db6
|
refactor: renderer.js拆分为6个模块(core/tabs/editor/search/sidebar/markdown)
|
2026-05-21 13:34:49 +08:00 |
|
thzxx
|
b185771c41
|
opt: 8项优化——搜索高亮精度/滚动同步/行号同步/本地图片/拖拽提示/MRU标签/侧边栏调宽/toast组件
|
2026-05-21 13:30:11 +08:00 |
|
thzxx
|
d178f5b3f6
|
feat: 侧边栏文件夹目录树添加标题头
|
2026-05-21 13:16:06 +08:00 |
|
thzxx
|
16fa87e7dd
|
chore: 删除重复的formatFileSize函数,统一用formatBytes
|
2026-05-21 13:05:21 +08:00 |
|
thzxx
|
04c904dc20
|
fix: 侧边栏始终可见,不因无文件而隐藏
侧边栏包含「打开文件夹」入口,隐藏会导致用户无法打开文件夹
|
2026-05-21 12:59:53 +08:00 |
|
thzxx
|
2d899cca7e
|
fix: 侧边栏高亮逻辑清理与边界情况修复
- 移除 loadTabState 中冗余的 updateSidebarHighlight 调用(switchToTab/closeTab 已覆盖)
- 无文件夹+无标签时自动隐藏侧边栏(之前会空显示)
- handleSave/handleSaveAs 后刷新侧边栏(文件路径变化时同步更新)
|
2026-05-21 12:59:02 +08:00 |
|
thzxx
|
eff04606bd
|
fix: 侧边栏高亮跟随标签切换同步更新,支持显示独立打开的文件
- 添加 updateSidebarHighlight() 函数,标签切换时只更新高亮状态而非重建整棵树
- 给树节点添加 data-path 属性用于精确定位高亮
- 新增「已打开的文件」区域,显示不在当前文件夹内的独立文件
- 独立文件支持点击切换、修改状态标识、活跃高亮
- 无文件夹打开时自动显示独立文件列表,全部关闭后隐藏侧边栏
|
2026-05-21 12:56:50 +08:00 |
|
thzxx
|
65383defd1
|
fix: 标签栏移入右侧内容区,左侧纯侧边栏
|
2026-05-21 12:06:14 +08:00 |
|
thzxx
|
d25c2ec30d
|
fix: banner移入content-wrapper,标签栏下方直接是两栏布局
|
2026-05-21 12:04:54 +08:00 |
|
thzxx
|
dbbd0f4abb
|
fix: 欢欢迎页移入main-content,侧边栏启动即可见
|
2026-05-21 12:03:02 +08:00 |
|
thzxx
|
9ac07d376b
|
fix: 修复侧边栏布局——sidebar与main-content并排显示
|
2026-05-21 11:59:56 +08:00 |
|
thzxx
|
f6f1c4f717
|
fix: 侧边栏watcher泄漏、目录刷新防抖、清理过时注释
|
2026-05-21 11:43:42 +08:00 |
|
thzxx
|
5d64e4401f
|
fix: 修复渲染进程5个bug(path未定义、editorWrapper未定义、死代码清理)
|
2026-05-21 11:41:23 +08:00 |
|
thzxx
|
2010f9dff5
|
docs: 同步 v1.2.0 文档(搜索替换 + 文件树)
|
2026-05-21 11:39:07 +08:00 |
|
thzxx
|
543af93802
|
feat: v1.2.0 搜索替换 + 文件树侧边栏
|
2026-05-21 11:37:02 +08:00 |
|
thzxx
|
c773a0d8e6
|
chore: 文件大小限制调整为20MB
|
2026-05-18 17:36:41 +08:00 |
|
thzxx
|
21d7b2da9f
|
fix: BOM处理、异步读取、10MB文件限制、滚动同步精度优化
|
2026-05-18 17:33:09 +08:00 |
|
thzxx
|
1a5ec08728
|
fix: marked兼容、保存竞态、关闭死锁、XSS防护、行号虚拟化、CSP加固
|
2026-05-18 17:23:26 +08:00 |
|
thzxx
|
320980030e
|
fix: 代码块预览显示undefined - renderer.code参数应为位置参数而非对象解构
|
2026-05-18 16:16:04 +08:00 |
|
thzxx
|
a85c3604c6
|
fix: 渲染成功后清除错误红色样式残留
|
2026-05-18 16:01:18 +08:00 |
|
thzxx
|
69e2ee0713
|
fix: 清理死代码、错误渲染防XSS、blob URL释放时机修复
|
2026-05-18 15:57:02 +08:00 |
|
thzxx
|
addf8e4dd1
|
fix: save写入失败时恢复文件监听、窗口销毁安全检查、暗色主题跟随系统偏好
|
2026-05-18 15:50:05 +08:00 |
|
thzxx
|
65451b938c
|
fix: 防御性检查补全
- openFileInTab 增加 isDestroyed() 前置检查
- open-file handler 增加 isDestroyed() 检查
- window:forceClose 增加 isDestroyed() 检查
- close handler 使用 isClosing 防止重入
- cancelClose 重置 isClosing 允许再次关闭
|
2026-05-18 15:24:01 +08:00 |
|
thzxx
|
5428beb6db
|
fix: 单实例锁,双击md文件在已有窗口打开
- 添加 requestSingleInstanceLock() 防止重复启动
- second-instance 事件中提取文件路径,转发给已有窗口
- 复用 getFilePathFromArgs() 解析命令行参数
|
2026-05-18 15:10:28 +08:00 |
|
thzxx
|
07989db28e
|
feat: 限制只能打开 md/txt 文件,新建文件仅保存为 md
- 打开对话框移除「所有文件」选项
- 保存对话框移除 .txt 选项
- 拖拽打开增加扩展名过滤
- 浏览器降级路径同步过滤
|
2026-05-18 14:16:34 +08:00 |
|
thzxx
|
9f0b4550d1
|
fix: 启动时不自动创建空标签页,直接显示欢迎页
|
2026-05-18 14:01:43 +08:00 |
|
thzxx
|
5b1caf046c
|
fix: shell.openExternal 添加协议白名单校验
仅允许 http/https 协议,阻止 javascript: 等潜在恶意链接。
|
2026-05-18 13:58:38 +08:00 |
|
thzxx
|
aac6a0b073
|
fix: 预览选择复制、关闭超时、链接跳转、监听器泄漏
1. 预览区无法选择复制 — #preview 添加 user-select: text
2. IPC 监听器重复注册 — 注册前先 removeAllListeners 防止堆叠
3. 关闭确认取消后 5s 超时仍强制关闭 — 新增 cancelClose IPC 清除超时
4. 预览区链接点击离开应用 — 拦截点击,通过 shell.openExternal 打开
5. 预览区链接光标样式 — .markdown-body a 添加 cursor: pointer
|
2026-05-18 13:55:02 +08:00 |
|