VS Code Markdown 阅读批注插件。选中一段文字 → 添加 Comment(可打 Tag)→ 收集 → 搜索/筛选 → 跳回原文 → 预览/管理 → 导出 AI 可读的 Markdown。
核心理念:MarkComment 不负责 AI,负责把阅读过程中的「注意力 + 思考」结构化保存,让 AI 能消费这些上下文。
Local-first,无后端,无账号,无云同步,无 AI API 调用。
核心能力:#tag/$tag 标签、Solved/Reopen、实时搜索、File/Tag/Status/Date 多维度筛选、Comment Preview(复用/多 Tab)。
项目结构
markcomment/
├── package.json # 扩展清单、命令、菜单、快捷键、视图
├── tsconfig.json
├── .vscode/ # launch / tasks
│
├── src/
│ ├── extension.ts # 入口:激活、注册命令/视图、加载数据
│ ├── context.ts # 运行时共享上下文组装(Store/Manager/Storage)
│ │
│ ├── commands/
│ │ ├── addComment.ts # 添加 Comment
│ │ ├── editComment.ts # 编辑 Comment
│ │ ├── deleteComment.ts # 删除 Comment
│ │ ├── solveComment.ts # 标记 Solved
│ │ ├── reopenComment.ts # 重新打开
│ │ ├── searchComments.ts # 搜索 + 筛选(实时)
│ │ ├── openCommentPreview.ts # 打开 Comment Preview
│ │ ├── jumpToSource.ts # 定位 + reveal + 高亮
│ │ └── exportCommands.ts # Copy / Export / Save As
│ │
│ ├── comments/
│ │ ├── types.ts # Comment 数据模型(含 tags/status)+ LocateResult
│ │ ├── commentStore.ts # 内存数据访问(add/update/delete/search + 迁移)
│ │ ├── commentManager.ts # 业务流程协调(create/edit/solve/reopen/delete)
│ │ ├── tagParser.ts # #tag / $tag 解析(纯函数)
│ │ └── locator.ts # 重定位策略(range→text→context)
│ │
│ ├── search/
│ │ ├── filterTypes.ts # Filters / SearchQuery 类型
│ │ └── searchService.ts # 搜索+筛选纯函数(AND 组合)
│ │
│ ├── preview/
│ │ ├── previewManager.ts # Preview 生命周期(reuse/new)
│ │ └── commentPreviewProvider.ts # Comment Preview Webview
│ │
│ ├── storage/
│ │ ├── storage.ts # Storage 接口
│ │ ├── jsonFileStorage.ts # JSON 文件读写 + 损坏备份
│ │ ├── workspaceStorage.ts # <workspace>/.vscode/markcomment.json
│ │ └── globalStorage.ts # context.globalStorageUri
│ │
│ ├── export/
│ │ └── markdownExporter.ts # Comment[] → Markdown 字符串(含 Tags/Status)
│ │
│ ├── views/
│ │ ├── commentTreeItem.ts # TreeItem 封装(含 status/tags 展示)
│ │ ├── currentFileView.ts # Current File 视图
│ │ ├── workspaceView.ts # Workspace 视图(按文件分组)
│ │ └── globalView.ts # Global 视图(按日期→文件分组)
│ │
│ ├── ui/
│ │ ├── commentInput.ts # 多行输入(#tag 快捷按钮 / Save / Cancel)
│ │ ├── commentCodeAction.ts # 小灯泡 CodeAction
│ │ └── decorations.ts # 黄色临时高亮
│ │
│ └── utils/
│ ├── time.ts # timestamp → 展示字符串 + 日期筛选
│ ├── path.ts # 文件名/扩展名/默认导出名
│ ├── markdown.ts # blockquote 转义、摘要
│ └── id.ts # UUID / workspaceId
│
├── test/ # 单元测试(node:test,纯 Node,不依赖 VS Code)
│ ├── comments/commentStore.test.ts
│ ├── comments/locator.test.ts
│ ├── comments/tagParser.test.ts
│ ├── comments/migrate.test.ts
│ ├── search/searchService.test.ts
│ ├── export/markdownExporter.test.ts
│ └── utils/time.test.ts
│
└── resources/icons/comment.svg
架构依赖方向(上层依赖下层,核心逻辑与 UI 解耦):
extension.ts ─► Commands / Views
│
▼
CommentManager ─► Locator / TagParser
│ (纯函数,可测)
▼
CommentStore ─► Storage(workspace / global)
SearchService ─► 搜索/筛选(纯函数)
PreviewManager ─► CommentPreview(复用/新建)
安装运行方法
- 安装依赖:
npm install
- 编译:
npm run compile
启动调试(F5):VS Code 会打开 Extension Development Host,在其中打开任意 .md 文件即可使用。
- 快捷键:
Cmd/Ctrl + Shift + C(需选中 Markdown 文本)
- 或右键菜单 →
Add Comment
- 或 Activity Bar 的 MarkComment 图标,打开三个视图
开发方法
npm run watch # 监听编译(配合 F5 调试)
修改 src/ 下代码后,在 Extension Development Host 用 Developer: Reload Window 重新加载。
模块职责边界:
- Store 只管数据增删查,不碰 UI/Editor。
- Locator 纯函数,输入文档全文 + Comment,返回
found/not-found/ambiguous,不碰 Editor。
- Exporter 纯函数,输入
Comment[],输出 Markdown 字符串,不碰文件系统。
- Command 尽量薄,只做「操作 → 调用业务模块 → 展示结果」。
测试方法
单元测试使用 Node 内置 node:test,只测不依赖 VS Code 的核心模块(Store / Locator / Exporter / utils):
npm test # 等价于 npm run test:unit
覆盖范围见 test/:
- Locator:range 未变化 / range 变化+text 唯一 / 多匹配 / context 定位 / 无法定位 / 多行。
- Store:add / update / delete / persist / 按 document、workspace 过滤 / search / 排序。
- Exporter:单/多 Comment、多文件、中文、Markdown 特殊字符、多行、反引号转义。
打包方法
npm run package # 生成 markcomment-0.1.0.vsix
本地安装:Extensions 面板 → … → Install from VSIX…。
发布(可选):npx @vscode/vsce publish(需 publisher 账号)。
已实现功能清单(V1.1)
- [x] Markdown 选择文本(仅
.md / .markdown,非 Markdown 优雅失败)
- [x] Add Comment(快捷键 / 右键菜单 / 命令面板 / 小灯泡 CodeAction)
- [x] 多行文本输入,支持中文 / 英文 / Emoji / Markdown 字符
- [x] 保存 selected text + original range + before/after context + comment + file + timestamp + ID + status + tags
- [x]
#tag / $tag 双前缀标签解析,多 Tag、去重保序、中文 Tag
- [x] 时间统一存 Unix 时间戳(毫秒)
- [x] Local 持久化:workspace JSON + global JSON(损坏自动备份,不崩溃)
- [x] Current File View / Current Workspace View / Global View
- [x] 实时搜索(评论 / 原文 / 文件名 / 路径 / Tag)
- [x] 多维度筛选:File(多选)/ Tag(多选)/ Status / Date,可组合(AND)
- [x] Solved / Reopen(
status: open | solved,Solved 仍可搜索/筛选/导出)
- [x] Comment Preview(点击复用 / 右键 New Tab 新建)
- [x] Preview 内含 Edit / Solved / Reopen / Delete / Jump
- [x] Locator 三级重定位:Range 验证 → Text 精确搜索 → Context 辅助
- [x] Locator 返回明确状态:found(含 method)/ not-found / ambiguous
- [x] Jump to Source(复用已打开 Editor → 定位 → revealRange → 黄色临时高亮)
- [x] Edit / Delete(仅更新内容,edit 不改 id/range/text/createdAt)
- [x] Export Markdown(含 Tags / Status,Current File / Workspace)
- [x] Copy as Markdown / Save Markdown As...
- [x] V1 数据迁移(缺 tags→[]、缺 status→open、resolved→solved)
- [x] 临时原文高亮(TextEditorDecorationType,主题变量适配)
未实现功能清单
P1(建议,未做)
- [ ] Save beside source(一键导出到源文件旁)
- [ ] Voice button(依赖系统语音输入,输入框本身已支持)
- [ ] 更漂亮的浮动 Add Comment UI
- [ ] Tag 管理(重命名/删除/统计)
P2(暂不做)
- [ ] 自定义日期区间筛选
- [ ] 多匹配候选位置手动选择 UI
- [ ] 文件移动自动更新 document 信息(
onDidRenameFiles 监听)
- [ ] Global Export 单独命令(按 workspace→file→comment 组织)
- [ ] MarkComment 自有 Markdown Preview(明确不做,后续版本)
已知问题
- 多 root 工作区:Workspace 存储当前只用第一个
workspaceFolders[0],多 root 场景仅第一个 folder 持久化。V1 未支持多 folder 单独存储。
- 文件移动:文件被移动/重命名后,
document.uri 不会自动更新(未接 onDidRenameFiles),依赖 Locator 重新定位能力,但 Jump to Source 会因旧 URI 失效显示 "Source file not found"。
- Global 与 Workspace 数据重复:Add Comment 同时写入 workspace 与 global 两份 JSON,删除/编辑需同步两处;若任一异常可能导致短暂不一致(已 try/catch 保护,不崩溃)。
- Comment Preview 复用语义:TreeItem 点击无法携带 Ctrl/Cmd 修饰键,故「Cmd/Ctrl+Click 新 Tab」通过右键「Open in New Tab」实现等价能力。
- 日期分组使用 ISO 字符串切片:Global View 按
toISOString() 的 UTC 日期分组,可能与用户在 UTC 边界的本地日期有偏差(数据本身无歧义,仅展示层边界问题)。
- 内存模型:Store 全量加载到内存,< 10000 comments 满足性能要求;未做懒加载/分页(PRD 明确无需针对 10w+ 优化)。