Skip to content

Text (character-range) comments: comment on a word / phrase / span - #83

Merged
adnaan merged 3 commits into
mainfrom
text-select
Jul 1, 2026
Merged

Text (character-range) comments: comment on a word / phrase / span#83
adnaan merged 3 commits into
mainfrom
text-select

Conversation

@adnaan

@adnaan adnaan commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Currently a comment can only anchor to whole lines. This adds sub-line, character-range comments: select a word, a phrase, or a span across lines — by mouse, touch, or keyboard — and comment on exactly that text.

What's new

  • New kind=text comment with FromCol/ToCol (0-based, half-open, rune offsets) + the selected snippet in the anchor. CSV gains from_col/to_col (reader stays length-tolerant, 7→15 cols).
  • Selectable diff: each line is now a selectable <div role=button tabindex=0> (was <button>, whose content iOS/UA make non-selectable) with a [data-line-text] container; click/Enter still select the line.
  • Client directive lvt-fx:text-select (vendored bundle; source in feat(dom): lvt-fx:text-select — character-range selection over diff text client#140): floating Comment button on drag/long-press, and a keyboard block caret (visible on load; ←/→/↑/↓; Shift+arrows select; Ctrl/Alt = word).
  • Persistent highlight: server-side gitdiff.MarkRanges wraps [FromCol,ToCol) in <mark class="comment-span"> (splits across chroma tokens), rendered via the zero-arg LineDisplay() map. Works with no JS, survives re-render, theme-aware.
  • Side-aware composer/cards: a modified line's number exists on both the old and new rows, so rendering is gated on the selected side (fixes a double-composer).
  • Drift: kind=text reuses line-anchor relocation, then relocateTextColumns re-finds the snippet in the moved line.

Why it's safe

  • Load-bearing invariant guarded by gitdiff/textcontent_test.go: a rendered line's .content textContent equals the raw line rune-for-rune — the only reason browser-computed offsets match server-stored ones.
  • Native copy (Ctrl+C / iOS long-press menu) is preserved — the feature augments selection, never suppresses it.

Tests

Unit: CSV round-trip + 7→15-col back-compat, MarkRanges (cross-token / unicode / fallback / merge), textcontent invariant, LineSpan/predicates, text-column drift. E2E (chromedp): mouse select→CSV, keyboard caret + select, visible-caret-moves, modified-line single-composer, mark highlight. Existing keyboard/line e2e all still green.

🤖 Generated with Claude Code

adnaan and others added 3 commits July 1, 2026 08:43
… (#text-select)

Comment on exactly a word, phrase, or multi-line span — by mouse, touch, or
keyboard — not just whole lines. Adds a new kind=text comment.

- Model: Comment.FromCol/ToCol (rune offsets) + Kind="text" +
  CommentAnchor.Snippet; CSV gains from_col/to_col (length-tolerant reader).
- Selectable diff: line <button> → <div role/tabindex> with [data-line-text];
  wires the upstream lvt-fx:text-select directive (vendored bundle).
- Server: SelectText handler + addTextComment + text composer mode +
  side-aware composer/card gate (a modified line exists on both sides).
- Highlight: server-side gitdiff.MarkRanges wraps [FromCol,ToCol) in
  <mark class="comment-span">, rendered via zero-arg LineDisplay().
- Drift: relocateTextColumns re-finds the snippet in a moved line.
- Load-bearing invariant guarded by gitdiff/textcontent_test.go
  (.content textContent == raw line, rune-for-rune).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ey41dRwDpRgLtVHZjhYLKt
…nt#140)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ey41dRwDpRgLtVHZjhYLKt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ey41dRwDpRgLtVHZjhYLKt
@adnaan
adnaan merged commit a41d0b5 into main Jul 1, 2026
7 checks passed
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