Skip to content

Add: Remark Mode — inline annotation for AI-assisted document review#76

Merged
xicilion merged 1 commit into
markdown-viewer:mainfrom
liyuankui:feat/remark-mode
May 14, 2026
Merged

Add: Remark Mode — inline annotation for AI-assisted document review#76
xicilion merged 1 commit into
markdown-viewer:mainfrom
liyuankui:feat/remark-mode

Conversation

@liyuankui
Copy link
Copy Markdown
Contributor

@liyuankui liyuankui commented May 12, 2026

Overview

This PR adds Remark Mode — an inline annotation feature designed to support AI-assisted document review workflows.

Closes #74


What is Remark Mode?

Remark Mode lets you select text in any rendered Markdown document, annotate it with a category tag and optional note, then copy the structured feedback to clipboard for use with AI assistants (Claude, GPT, etc.).

The exported format is:

I reviewed this file and have the following feedback:

1. [🟡 Suggestion] L23–L25: "selected text here"
   Note: "your note here"
2. [🔵 Question] L40: "another selection"

This allows an AI agent to receive precise, line-referenced feedback and apply changes.


Implementation

New file: src/ui/remark-mode.ts

  • Self-contained Remark Mode controller (no external deps beyond Chrome storage)
  • Block-level annotation using existing data-line / data-line-count attributes on rendered blocks
  • Persistence via chrome.storage.local (keyed by page URL)
  • Fallback to localStorage for non-extension contexts

Modified files

  • chrome/src/webview/ui/toolbar.ts — ✏️ toggle button with annotation count badge
  • chrome/src/webview/viewer-main.ts — wires Remark Mode container + raw markdown
  • src/types/toolbar.ts — new optional fields on ToolbarManagerOptions
  • chrome/src/host/background.ts — fix pre-existing duplicate context menu ID bug

Screenshot

Screenshot

Features

Feature Details
Toggle ✏️ toolbar button, exits when Source Mode is entered
Select to annotate Click any rendered block → popup with color picker + note
Color categories 🟡 Suggestion · 🔵 Question · 🩷 Concern · 🟢 Keep
Highlight Selected blocks visually highlighted with category color
Hover tooltip Hovering highlighted block shows annotation note
Right sidebar All annotations listed, sorted by line number
Inline editing Click note in sidebar → textarea → Enter/blur to save
Scroll-to-block Click annotation header/quote → scrolls document to block
Delete ✕ in sidebar or click emoji badge on block
Count badge Red badge on ✏️ button shows annotation count
Persistence Survives page refresh via chrome.storage.local
Done button ✓ Done → copies structured feedback → exits mode

Design decisions

  • Block-level only (not arbitrary text ranges): leverages existing data-line attrs, survives re-renders, no fragile DOM range serialization
  • No new build deps: plain TypeScript, CSS-in-JS styles injected once
  • Storage key = page URL: annotations are per-document
  • Independent panel: does not conflict with workspace mode file/TOC panels; workspace mode integration is out of scope for this MVP per discussion in Feature Request: Remark Mode — AI 协作中的文档标注闭环 #74

Testing

  1. Load unpacked from dist/chrome/ after npm run build:chrome
  2. Open any local .md file in Chrome
  3. Click ✏️ in toolbar → Remark Mode activates
  4. Select text in any block → popup appears → add note → Save
  5. Verify highlight + badge appear on block, annotation appears in sidebar
  6. Hover highlighted block → tooltip shows note
  7. Click sidebar item → scrolls to block
  8. Click note in sidebar → edit inline
  9. Click ✓ Done → copies formatted feedback → mode exits
  10. Refresh page → annotations persist

This PR is a reference implementation accompanying Issue #74. The author (xicilion) plans to implement their own version following markdown-viewer's internal layout conventions. This PR demonstrates the feature scope and approach.

@xicilion
Copy link
Copy Markdown
Member

Screenshot 2026-05-12 at 15 43 23 有批注时,刷新页面,角标样式丢失了。

@xicilion
Copy link
Copy Markdown
Member

Screenshot 2026-05-12 at 15 44 36 这里的 Done 感觉语义不清楚,我点击才知道是复制。

@xicilion
Copy link
Copy Markdown
Member

Screenshot 2026-05-12 at 15 46 02 既然批注是以段落为单位,弹出批注的时候,我觉得应该将段落标记一下。

@xicilion
Copy link
Copy Markdown
Member

Screenshot 2026-05-12 at 15 48 48 虽然提示不多,但是也要做一下语种支持。 并不复杂,你可以让 ai 一次生成 json,然后 scripts/update-locale-keys.js 批量更新。

@xicilion
Copy link
Copy Markdown
Member

目前不支持图表批注,悬浮在图表或者图片上的时候,可以不显示焦点边框。

@xicilion
Copy link
Copy Markdown
Member

最后,复制批注之后,是不是可以发送给别人,导入到批注面板?这样就可以协同工作了。

@xicilion
Copy link
Copy Markdown
Member

总体而言这个功能太赞了,我迫不及待想要用了哈哈哈。

@xicilion
Copy link
Copy Markdown
Member

Screenshot 2026-05-12 at 15 57 59 Screenshot 2026-05-12 at 15 58 50

还有一处,你可以复用文件树面板的实现,一方面不用重新对齐面板,另一方面可以兼容左右面板切换。

@liyuankui
Copy link
Copy Markdown
Contributor Author

感谢详细的 review!已在最新 commit 中修复所有问题,逐一回复:

✅ 已修复(本次 commit)

  1. 角标丢失(刷新后):根本原因是 loadAnnotations 在 markdown DOM 渲染完成前就调用了 renderHighlights。改为用 MutationObserver 监听容器,等到第一个 [data-line] 元素出现后再渲染角标,解决了异步时序问题。

  2. Done 语义不清:已改为 📋 Copy remarks,tooltip 说明"Copy all annotations to clipboard",点击后按钮变成 ✓ 短暂反馈,语义更清晰。

  3. 段落未标记:弹出批注面板时,对应段落现在会加上 .remark-popup-target 高亮样式(左边框 + 浅色背景),关闭弹窗时移除。

  4. i18n 支持:所有 UI 字符串已包装在 t() helper 中(内部调用 chrome.i18n.getMessage,不可用时降级为英文)。使用 update-locale-keys.js 脚本批量生成了 en / de / es / fr / ja / ko / zh_CN / zh_TW 8 个语种。其余语种自动 fallback 到英文。

  5. 图表/图片 hover 焦点边框:已跳过 img、svg、canvas、video、figure 等媒体块的 hover 和选区处理,不再显示焦点边框。

📋 已知待做(后续迭代)

  • 导入批注(协同):复制内容格式已标准化为带行号的 JSON,理论上可以解析后导入。这个功能比较大,计划在 MVP 合并后另开 issue/PR 实现。

  • 复用文件树面板:完全认可这个方向,可以避免重复对齐逻辑并天然支持左右切换。这次先聚焦修复,重构面板留在下一个 PR。

再次感谢,这个项目太棒了!🎉

@liyuankui liyuankui marked this pull request as draft May 13, 2026 14:12
@liyuankui
Copy link
Copy Markdown
Contributor Author

更新一下进展:刚刚 force push 了最新版本,在上次修复的基础上又做了几件事:

🧪 代码质量

  • 从闭包中提取了 6 个纯函数到独立模块 remark-utils.ts(truncate、formatLineRef、rangesOverlap 等),36 个单元测试全部通过
  • 修复了 lineRef 格式不一致的 bug(sidebar 显示 L5–10,export 显示 L5–L10,现在统一为 L5–L10
  • 截断算法现在支持 CJK 字符双宽度计算(中文字、全角标点都算 2 宽度)

✨ UX 微交互

  • 弹窗 scale-in 动画(0.15s 弹性曲线)
  • 颜色按钮增加文字标签(不再只有 emoji)
  • 删除 undo 增加底部进度条 + 倒计时显示
  • 全部动画遵循 prefers-reduced-motion

⌨️ 键盘支持

  • Ctrl+Shift+M(macOS ⌘+Shift+M)全局切换 Remark Mode
  • Shift+方向键选择文字后自动触发标注弹窗(300ms 防抖)
  • 第 3 条标注时显示键盘提示(sessionStorage 只显示一次)

♿ 无障碍

  • undo 区域增加 role="status" aria-live="polite"

关于后续:复用文件树面板和**导入批注(协同)**计划在 MVP 合并后单独 PR 实现。

Remark Mode enables reviewers and AI agents to annotate rendered Markdown
documents at the block level. Designed for the Remarker human-AI review loop.

Core features:
- Block-level selection & annotation with color coding (🟡🟢🔵🩷❓)
- Persistent storage via chrome.storage.local (keyed by origin+pathname)
- Right sidebar panel with TOC-style positioning (auto-switches to left when TOC is on right)
- Smooth slide-in/out animation with content margin transition
- Hover tooltips showing annotation content on highlighted blocks
- Inline note editing with auto-expanding textarea (max 5 lines)
- Export to clipboard in structured format with filename from URL
- Undo-on-delete with 5-second soft-delete toast
- Auto-activate via ?remarker=true URL parameter
- Badge count on toolbar button (gray, non-intrusive)
- i18n support for 8 locales (en/de/es/fr/ja/ko/zh_CN/zh_TW)
- Media block skip (img/svg/canvas/figure/video)
- MutationObserver for async-rendered DOM

Technical notes:
- Badge uses inline styles to avoid timing dependency on CSS injection
- URL normalization strips hash/query for consistent storage key
- scheduleHighlightsAfterRender watches document.body first when container
  is not yet in DOM, then watches container for [data-line] elements
- onModeChange callback uses inline logic (not hoisted function reference)
  due to TypeScript block-scoped function declaration semantics
- Context menu duplicate ID guard in background.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@liyuankui
Copy link
Copy Markdown
Contributor Author

liyuankui commented May 14, 2026

Update: removed keyboard shortcut (Alt+Shift+R) — conflicts with browser/OS bindings on macOS. Will revisit via manifest.commands in a future PR where users can customize their own binding.

Kept:

  • ✅ Popup scale-in animation, color ink splash, undo progress bar
  • ✅ Color button labels (emoji + text)
  • ?remarker=true URL parameter for auto-activation (agent-friendly)
  • ✅ Unit tests (36 cases, remark-utils.ts pure functions)
  • ✅ aria-live on undo row

Also submitted a remark skill PR to markdown-viewer/skills (markdown-viewer/skills#2) — teaches AI agents how to install the extension, open files with ?remarker=true, and process the structured export format.

@liyuankui liyuankui marked this pull request as ready for review May 14, 2026 13:22
@xicilion xicilion merged commit 045238f into markdown-viewer:main May 14, 2026
@liyuankui liyuankui deleted the feat/remark-mode branch May 15, 2026 06:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Remark Mode — AI 协作中的文档标注闭环

2 participants