Skip to content

feat: highlight, annotate, and copy passages as agent-ready changelist (#5)#9

Open
JohnnyBonk wants to merge 3 commits intoGRVYDEV:mainfrom
JohnnyBonk:feat/highlight-and-changelist-export
Open

feat: highlight, annotate, and copy passages as agent-ready changelist (#5)#9
JohnnyBonk wants to merge 3 commits intoGRVYDEV:mainfrom
JohnnyBonk:feat/highlight-and-changelist-export

Conversation

@JohnnyBonk
Copy link
Copy Markdown

@JohnnyBonk JohnnyBonk commented Apr 29, 2026

Implements the highlight + annotate + agent-export workflow from #5, plus a small unrelated UX change for the sidebar.

Summary

  • Select markdown text → choose a colour or annotate with a note.
  • Click an existing highlight → recolour, edit the note, copy, or delete.
  • Right-side panel groups highlights by colour, with per-list and per-item copy in agent-ready format.
  • Highlights persist per file in app_data_dir/highlights.json.
  • Sidebar folders now default to collapsed.

Scope

Highlights — capture

  • Selection popover with five colour swatches (yellow / orange / pink / blue / purple) plus Annotate and Copy.
  • Number keys 15 apply the matching colour while the popover is open.
  • Annotate swaps the popover row to an inline note input; Enter / Save creates the highlight in the active colour with the note attached.
  • Active colour is persistent for the session; ] / [ cycle it without opening the popover.
  • Code blocks are not highlightable in v1 (selection inside <pre> hides the popover).
  • Welcome tab supports highlights via a synthetic :welcome storage key.

Highlights — re-engage

  • Click an existing highlight → edit popover anchored to the span: current colour, recolour swatches, note display + edit, Copy, Delete.
  • Delete / Backspace deletes the targeted highlight while the popover is open or the cursor is inside one.
  • Inline checkmark flash on Copy and Delete buttons; bottom-right toast for global confirmation; Undo action (5s) on every delete path.

Review panel

  • Toggle from the toolbar (highlighter icon, with an active-colour pip).
  • Filter pills per colour with counts; "Copy all" / "Copy <colour>" in the header.
  • Per-item note display and edit (pencil icon, hover-revealed).
  • Click an item → scrolls the document highlight into view.

Agent-ready export format

Single item:

Source: /abs/path/to/README.md

> the selected passage
Section: Installation
Timestamp: 2026-04-29T10:43:12Z
Note: optional annotation

Whole list (per-list Copy) groups by colour:

Source: /abs/path/to/README.md

## List: pink

> uncited claim
Section: Performance benchmarks
Timestamp: 2026-04-29T10:44:27Z

Anchoring

Highlights store (sourceStartLine, sourceEndLine, passage, occurrenceIndex), leveraging the data-source-map attributes markdown-it already emits on block-level tokens. Re-applied as wrapping spans on every render, so they survive Shiki / Mermaid replacement passes. If a passage cannot be relocated after an upstream edit, the highlight is silently skipped (orphaned). Scroll position is saved and restored around the re-application pass to prevent browser scroll-anchoring from snapping to the top when the wrapper used as the anchor is removed during delete.

Persistence

  • Single highlights.json under app_data_dir, keyed by absolute file path.
  • Schema is forward-compatible: the note field uses serde(default, skip_serializing_if) so older files load cleanly and unannotated highlights stay compact.
  • Two new Tauri commands: load_highlights and save_highlights_for_file.

Sidebar folders default to collapsed

Per-folder expansion state defaults to collapsed; the sidebar opens quietly each session and the user expands what they want. Repo-group headers (when grouping by repo) still default open so the outline stays visible.

Tests

  • 27 Vitest cases covering anchoring, occurrence counting, agent-export formatting (with and without notes), and per-colour grouping.
  • 7 Rust tests covering round-trip, missing/corrupt file fallback, camelCase JSON keys for the frontend, legacy file (without note) loads cleanly, and note omitted from JSON when unset.
  • pnpm typecheck and pnpm build clean.
  • Pre-existing failures in src/lib/markdown.test.ts and src/lib/theme.test.tsx also fail on main and are unrelated to this change.

Deferred (for follow-ups)

  • Per-list description ("rules that apply to every item in the list").
  • Renameable colour → list label.
  • Pipe-to-agent integration.
  • Multi-block selections (current implementation anchors to the start block).
  • Snap-to-word selection.
  • JSON / markdown-blockquote export format toggles.
  • Sidecar JSON option (current store is global to app_data_dir).
  • Edit history per highlight.
  • Orphan UI for highlights whose passage can no longer be located.

Test plan

  • pnpm install (the repo currently imports markdown-it-front-matter; this branch has it in the lockfile).
  • pnpm tauri dev, open a markdown file with multiple paragraphs and headings.
  • Click the highlighter button in the toolbar to open the panel.
  • Select a passage; popover appears below the selection. Apply a colour via swatch or 15.
  • Click Annotate, type a note, press Enter; highlight is created with the note.
  • Click an existing highlight; edit popover appears. Recolour with a swatch, edit the note, then Copy. Confirm checkmark flash + toast.
  • Click Delete on the popover; confirm inline "Deleted" flash + bottom-right Undo toast. Click Undo within 5s; highlight returns.
  • With cursor inside a highlight, press Delete; same flow.
  • Press ] and [ to cycle the active colour.
  • In the panel, click a colour pill to filter, then "Copy" the visible list. Paste to verify format.
  • Try selecting inside a fenced code block; popover should not appear.
  • Reload Marky; highlights persist (~/Library/Application Support/marky/highlights.json on macOS).
  • Edit the source file (typo elsewhere in the doc); existing highlights still appear.
  • Sidebar: folders should be collapsed on first launch; expand state is per-session.

…v1)

Adds the v1 cutline of issue GRVYDEV#5: select text in the rendered markdown,
pick a colour, then copy a single item or whole list to the clipboard
in a format coding agents can act on directly.

What's in v1
- Selection in the article surfaces a small popover with five colour
  swatches (yellow / orange / pink / blue / purple) plus a "Copy"
  shortcut. Keyboard 1-5 applies the matching colour, Esc dismisses.
- A right-side review panel (toolbar toggle) lists the current file's
  highlights grouped by colour. Each list and each item has its own
  copy button. Clicking an item scrolls the source highlight into view.
- Highlights are anchored by source-line range + passage text +
  occurrence index, leveraging the data-source-map attributes that
  markdown-it already emits. Re-applied as wrapping spans on every
  render, so they survive Shiki / Mermaid replacement passes.
- Persistence is a single highlights.json under app_data_dir, keyed by
  absolute file path. New Tauri commands: load_highlights and
  save_highlights_for_file.
- Code blocks are not highlightable in v1 (selection inside <pre>
  hides the popover).
- IBM colorblind-safe palette, distinguishable to protanopes.

Tests
- 24 new Vitest cases for the pure helpers (anchoring, occurrence
  counting, agent export formatting).
- 5 new Rust tests for the persistence module (round trip, missing
  file, corrupt file, camelCase JSON keys for the frontend).
- Pre-existing failures in src/lib/markdown.test.ts and
  src/lib/theme.test.tsx also fail on main and are unrelated to this
  change.

Deferred to v2 (kept the diff focused)
- Annotations on highlights and named/described lists.
- Edit history with archive/restore.
- Multi-select copy.
- Customisable palette and JSON / markdown-blockquote export formats.
- Sidecar JSON next to source files (current store is global, which
  follows the project convention of not writing user data outside
  app_data_dir).

Closes the highlighting half of GRVYDEV#5.
The folder-disambiguation half is owned by the maintainer.
- Optional `note` field on Highlight, rendered as `Note:` in agent
  exports. Older highlights.json files load via serde default.
- Click an existing highlight to open an edit popover (recolour,
  edit note, copy, delete). Delete / Backspace also deletes the
  targeted highlight while the popover is open or the cursor is
  inside one.
- Annotate button on the new-selection popover swaps the row to an
  inline note input; Enter / Save commits with the active colour.
- Centralised toast / notification system. Inline checkmark flash
  on Copy and Delete buttons for local confirmation; bottom-right
  toast for global confirmation; Undo (5s) on every delete path.
- Panel: filter pills per colour, per-item note display and edit,
  copy-visible button in the header.
- `]` / `[` cycles the active colour at any time.
- Welcome tab supports highlighting via a synthetic `:welcome`
  storage key.
- Save and restore scrollTop around highlight re-application so the
  browser does not snap scroll back to the top when the wrapper
  used as the scroll-anchor is removed during delete.
- Tests: 3 new Vitest cases (note in formatItem / formatFile);
  2 new Rust tests (legacy-without-note loads cleanly, note absent
  from JSON when unset).
Per-folder expansion state defaults to collapsed when no explicit
state has been set, so the sidebar opens quietly and the user
expands what they want to scan. Repo-group headers still default
open so the outline stays visible at a glance.

Toggle handler now flips the resolved visual state rather than the
raw stored value, so the first click after the default change
correctly opens the folder.
@JohnnyBonk JohnnyBonk changed the title feat: highlight passages and copy as agent-ready changelist (closes the highlighting half of #5) feat: highlight, annotate, and copy passages as agent-ready changelist (#5) Apr 29, 2026
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.

1 participant