Skip to content

Let a reader comment on a line that carries a reference - #210

Merged
HamptonMakes merged 2 commits into
mainfrom
saip/fix-comment-on-reference-lines
Sep 4, 2026
Merged

Let a reader comment on a line that carries a reference#210
HamptonMakes merged 2 commits into
mainfrom
saip/fix-comment-on-reference-lines

Conversation

@saip-block

@saip-block saip-block commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Selecting a line to comment on it broke when the line carried a footnote citation. The hover card opened mid-drag, right over the text being swept — and if you got a selection out anyway, the server refused it with "Anchor text doesn't match the plan content — the comment would have nowhere to appear."

Three causes, none of them the same bug.

The preview opened mid-gesture

A held button means the reader is sweeping a selection across the line, not resting on a reference. Each entry point now reads that for itself, so there's no flag to leave stranded when a gesture ends without a mouseup — a link drag, a release outside the window. mouseenter carries the button state, and the focus Chromium fires on mousedown answers with :focus-visible, which a press never matches but keyboard and assistive-technology focus always do. That question is asked as the card is about to open rather than while the focus event is still dispatching, because Chrome settles :focus-visible afterwards and reading it inline intermittently turns a keyboard reader away.

The extractor read the document with the wrong grammar

MarkdownTextExtractor parsed with bare Commonmarker.parse while the renderer parses with footnotes: true. So the canonical text kept [^label] verbatim while the reader saw a superscript number, and no selection carrying that number could ever match. It now parses with the renderer's own EXTENSION_OPTIONS and emits the number the reader sees.

The digits are sentinel-mapped, like every other synthetic character here. That falls out nicely: a selection that merely ends on the marker resolves back to the prose before it rather than to half a citation.

Whitespace — and this one isn't about references at all

A browser hands back a selection with whitespace runs collapsed to a single space; a hard-wrapped paragraph is one flowing line on screen and the reader swept it as one. The extractor keeps the source's own newlines, so any selection crossing a wrapped line was refused, prose or not. Both sides now fold the same way, carrying the position map so ranges still land on real source positions.

Resolution and occurrence counting fold identically. They have to agree, or they disagree about which copy of a repeated phrase was selected and the highlight lands on the wrong one — nothing covered that before, so there's now an example with a repeated phrase spanning a wrap.

Verification

16 examples, each verified to fail when its guard is removed. The system example drives a real Selenium drag across the citation, through the comment form, to a placed anchor; reverting the extractor reproduces the reported error verbatim:

Anchor text doesn't match the plan content — the comment would have nowhere to appear
anchor: "This claim has evidence.1 See §2"

Full suite 1980 examples / 0 failures. RuboCop clean across 489 files. Also confirmed by hand in dev on a plan carrying both a citation and a section link.


Demos

Before

before-coplan.mov

After

after-coplan.mov

saip-block and others added 2 commits September 3, 2026 16:50
…e way

Selecting a line to comment on it broke when the line carried a footnote
citation or a numbered-section link: the hover card opened mid-drag,
directly over the text being swept.

- enter() turns away a mouseenter that arrives with a button held, and a
  focus that does not match :focus-visible — which is the focus Chromium
  fires on mousedown, but never the one a keyboard reader earns. Each
  entry point reads the gesture for itself, so there is no flag to strand
  when a drag ends without a mouseup.
- The :focus-visible test runs as the card is about to open rather than
  inside the handler. Chrome settles that state after dispatching focus,
  and reading it inline turned keyboard readers away about one time in
  five.
- follow() deliberately does NOT veto the jump when a selection is live.
  It cannot mean "this click is the tail of a sweep": the browser
  dispatches a sweep's click on the common-ancestor paragraph rather than
  the anchor, and refuses to start a selection from a press on a link at
  all. So the selection always predates the press and the click is always
  deliberate — and swallowing it strands the reader, because clicking a
  link never collapses a selection, so every retry is swallowed too. The
  new example pins that against a well-meant future patch.

Four system specs, each verified to fail when its guard is removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Selecting a line to comment on it was refused outright — "Anchor text
doesn't match the plan content" — whenever the selection crossed a
footnote citation, for two unrelated reasons.

The extractor read the document with a different grammar than the
renderer wrote it with: bare Commonmarker.parse against the renderer's
footnotes: true. So the canonical text kept `[^label]` verbatim while
the reader saw a superscript number, and no selection carrying that
number could ever match. It now parses with the renderer's own
EXTENSION_OPTIONS and emits the number the reader sees. The digits are
sentinel-mapped, like every other synthetic character here, which also
means a selection that merely ends on the marker resolves back to the
prose rather than to half a citation.

The second cause has nothing to do with references: a browser hands back
a selection with whitespace runs collapsed to a space, since a
hard-wrapped paragraph is one flowing line on screen, while the
extractor keeps the source's newlines. Any selection crossing a wrapped
line failed, prose or not. Both sides now fold the same way, carrying
the position map so ranges still land on real source positions.

Resolution and occurrence counting fold identically — they have to agree
or they disagree about which copy of a repeated phrase was selected, and
the highlight lands on the wrong one.

Twelve examples, each verified to fail when its guard is removed. The
system example drives a real drag across the citation through to a
placed anchor; reverting the extractor reproduces the reported error
verbatim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@saip-block
saip-block marked this pull request as draft September 4, 2026 14:21
@saip-block
saip-block marked this pull request as ready for review September 4, 2026 17:42
@HamptonMakes
HamptonMakes merged commit e7dc073 into main Sep 4, 2026
6 checks passed
@HamptonMakes
HamptonMakes deleted the saip/fix-comment-on-reference-lines branch September 4, 2026 18:25
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.

2 participants