markview 是一个本地运行的 Markdown 只读展出面:把本机多个 Markdown 文件快速投射到浏览器,以更高可读性和更强交互能力进行阅读、导航、演示与导出。
产品策略(问题、做法、用户、轨道)见根目录 STRATEGY.md;落地成熟度见 strategy-status.md。
核心目标:
- 零心智负担启动:一条命令即可打开预览。
- 多文件协同阅读:支持分组、重排、树视图、全文搜索、链接跳转。
- 实时反馈:文件保存后自动刷新内容。
- 会话可恢复:关闭后可恢复上次状态。
- 展出可带走:Slides 演示、PDF 导出、
markview build静态站(见 export-and-static.md)。
刻意不做:应用内编辑、云端协作编辑(写作交给 agent / 外部编辑器)。
- 本地优先
- 服务默认运行在本机端口,数据不依赖云端存储。
- 单实例优先
- 同端口已有服务时复用现有服务,而非重复拉起进程。
- 渐进增强
- 基础 Markdown 浏览可用;图表、搜索、图谱等能力按需增强。
- 状态可追溯
- 重要状态持久化,重启与故障恢复后可继续工作。
- 文档驱动开发者(README、ADR、设计文档维护)
- 技术写作者(教程、知识库、研究笔记)
- AI 辅助编码工作流用户(需要稳定的本地文档视图)
- 打开多个文档并分组查看(例如
design/notes) - 监听目录内新增 Markdown 文件并自动加入
- 在文档中点击相对链接自动打开目标文件
- 关闭服务后再次启动,恢复上次文件与分组
- 文件以
FileEntry表示,核心字段:id、name、path。 - 分组以
Group表示,映射到 URL 路径(如/design)。 - 默认分组名为
default。
文件 ID 设计:
- 常规文件:基于绝对路径的 SHA-256 前 8 位,稳定且可深链。
- 上传文件:基于内容哈希生成上传 ID(
uxxxxxxx)。
命令行启动时先探测 /_/api/status:
- 若服务存在:通过接口将文件或模式加入现有会话。
- 若服务不存在:启动新服务并打开浏览器。
这可避免同端口多进程竞争,并让命令行调用天然支持“追加文件”。
- 后端使用
fsnotify监听文件变化。 - 前端通过服务端事件流 (
/_/events) 订阅事件:update:文件集或分组变化file-changed:文件内容变化started:服务进程身份(PID)
当进程 PID 变化时,前端自动刷新页面,保证重启后的会话一致性。
- 存储位置:
$XDG_STATE_HOME/markview/backup/markview-<port>.json - 保存内容:分组、文件路径、监听模式、上传文件内容
- 写入策略:原子写入(临时文件 + rename)
- 触发策略:状态变更后去抖保存
主要交互能力:
- 侧边栏平铺/树形视图切换
- 分组切换与文件拖拽重排
- 目录树折叠状态记忆
- 目录面板(ToC)、原文视图(Raw)、宽窄阅读模式
- 全局全文搜索与命中跳转
- 图谱与大纲视图(链接关系可视化)
持久化策略:
- 前端 UI 偏好写入
localStorage(统一markview-前缀)
- 单实例减少资源浪费
- 前端按需加载/分包(Shiki/Mermaid/D3/PDF 等)
- 搜索与图谱构建以当前打开文件范围为边界
- Go 后端与 React 前端边界清晰
- API 路由统一
/_/api/前缀,避免与 SPA 路径冲突 - 测试覆盖 Go 单测与前端 Vitest
- 默认本地使用;非回环地址绑定会给出风险确认
- 对路径访问进行基本约束(如原始文件访问防目录穿越)
- 上传文件为内存态,不支持文件系统实时刷新。
- 监听与搜索范围是“已加入会话的文件集合”,不是全盘索引。
- 远程可访问模式(非 loopback 绑定)需用户明确确认,适合可信网络。
与 STRATEGY.md 四条轨道对齐(细节见 strategy-status.md):
- 演示质感:转场 / deck 导出、独立提词器、排版启发式(进度与备注已落地)
- 阅读 / review 定点打磨:搜索键盘导航与防抖、大规模文档下的 Worker 化搜索
- 导出与静态发布:
build/Pages 包装体验、多分组静态、导出保真 - 图表深度:离线 PlantUML、导出时图表一致性(不做插件市场)
工程债(穿插进行):
MarkdownViewer继续拆分,降低单文件复杂度- 远程访问模式的鉴权与更细粒度权限控制