Felix #7: handleMentionClick unconditionally preventDefault'd and goto'd,
breaking ctrl-click / cmd-click / shift-click / alt-click / middle-click —
"open in new tab" is a real workflow for researchers comparing two persons.
Add isPlainPrimaryClick() guard. Modified clicks fall through to the
browser's default anchor handling (the <a href="/persons/{id}"> opens in
the new tab as expected). Plain left-clicks still SPA-navigate via goto().
Three new tests assert ctrl-click, meta-click, and middle-click are not
preventDefault'd.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Composes splitByMarkers + renderTranscriptionBody so [unleserlich]
markers render as <em data-marker> siblings of the mention anchor —
neither nested inside the other (B19b).
Hover card lifecycle on each .person-mention anchor:
mouseenter → set aria-describedby, place card via getBoundingClientRect
(default below-right; flip up if <200px from bottom or
mention is in bottom 30% of viewport; flip left if
<300px from right), fire fetch, mount card with
skeleton state
resolved → swap card to loaded state with person + family
relationships (PARENT_OF / SPOUSE_OF / SIBLING_OF only)
404 → degrade: mark anchor with data-person-deleted="true",
unmount card, suppress future hovers/clicks
network → swap card to error state — link still navigates
mouseleave → drop aria-describedby, unmount card
Per-page SvelteMap<personId, Promise> cache (B15.5) so a sweep across
N mentions of the same person fires the backend once. Click handler
calls goto() so SvelteKit handles routing without a full reload.
Event listeners are attached once per article via a Svelte action
because the anchor HTML is injected via {@html ...} and would not
receive declarative bindings. The eslint-disable comment mirrors
the rationale on CommentMessage.svelte:88-89.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The b2 fixture in the second describe block had been missed when the
TranscriptionBlockData type added the mentionedPersons field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TranscriptionBlockData now carries mentionedPersons (matches backend
schema added in PR-A).
- useBlockAutoSave.saveFn signature widens to (blockId, text, mentions);
pendingMentions is tracked alongside pendingTexts and is preserved on
failure so a retry resends the in-flight payload (B12).
- TranscriptionBlock.svelte renders <PersonMentionEditor>, exposing the
textarea node back through a captureTextarea callback so the existing
quote-selection feature still works.
- saveBlock in routes/documents/[id]/+page.svelte forwards mentions on
PUT.
- flushOnUnload sends mentions in the keepalive payload too.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renders transcription blocks as readable text with [unleserlich]/[...]
markers styled as italic muted text. Supports click-to-sync and
flash highlight for scroll-sync feedback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>