Repository navigation
feat(remark): fine-grained annotation granularity for tables, lists, and code blocks - #85
Merged
xicilion merged 2 commits intoMay 21, 2026
Conversation
liyuankui
force-pushed
the
feat/remark-annotation-granularity
branch
from
May 19, 2026 15:57
05be69a to
6f2957c
Compare
Improves annotation precision for large blocks: instead of tagging an entire table, list, or code block, Remark Mode now narrows to the specific row, list item, or code line the user selected. - **Tables**: selection snaps to the exact TR row(s) → annotation covers only those line(s), not the entire multi-row table. - **Lists**: supports nested lists; annotation covers the LI item (and its nested content) the user actually selected. - **Code blocks**: annotation targets the exact line(s) within a fenced code block, not the whole block. - Headings, paragraphs, and other single-line blocks are unchanged. Fixes a bug where selecting all text in a heading produced L34–L36 instead of L34. The browser sometimes places range.endContainer on the next block element at offset 0; detect this case and treat the selection as single-block. Fixes highlights not appearing after page refresh when URL contains ?remarker=true. Root causes: 1. enter() skipped scheduleHighlightsAfterRender() when ≥1 block was already in the DOM, so later streamed blocks missed highlights. 2. The MutationObserver disconnected on the first [data-line] addition, missing remaining streamed chunks. Fix: enter() always calls scheduleHighlightsAfterRender(); observer now uses debounce + only reacts to new [data-line] additions (prevents infinite loops from highlight spans) + self-disconnects after 3 s of inactivity (15 s hard cap). 56 unit tests — all passing. New tests: TR/LI/code narrowing with ASCII-diagram documentation, heading single-line regression, and Range boundary edge case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
P0 UX overhaul for Remark Mode: - Replace countdown-based delete with optimistic delete + undo toast - Batch multiple deletes into single toast with count - Filter softDeletedIds from highlights, sidebar, badge count, and export - Choreograph exit: toolbar→popup→highlights fade→sidebar slide→cleanup - Replace subtle flash with ring-pulse landing animation (1s, box-shadow) - Remove stale countdown/progress CSS; add toast, exiting, landing styles Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
liyuankui
force-pushed
the
feat/remark-annotation-granularity
branch
from
May 21, 2026 01:51
facbf9a to
00d4a90
Compare
1 of 9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When annotating long blocks in Remark Mode, the line reference spans the entire block — e.g., selecting one cell in a 10-row table produces
L28–L37. This makes the exported feedback hard for AI agents (and humans) to locate precisely.Solution
Narrows the annotation line reference to the specific sub-element selected:
blockStart, tbody[i] =blockStart+2+i<li>index within block (off by ≤1 for multi-line items)Visual feedback: selected table rows and list items also receive a colored highlight (4 color variants each).
Architecture
Extracted
findTrLineInBlock,findLiLineInBlock,findCodeLineInBlock, andnarrowLineInBlockfrom theinitRemarkModeclosure intoremark-utils.ts:findBlockRangedelegates throughnarrowLineInBlockfor both single-block and cross-block selectionsTests
18 new unit tests added (55 total, all passing via
node --test):findTrLineInBlock: thead, tbody row 0/1, non-table node, text-node inputfindLiLineInBlock: first/third item, not-in-list, nested list document orderfindCodeLineInBlock: no-pre block, offset 0, after 1 newline, second text-node, not-foundnarrowLineInBlock: table dispatch, list dispatch, plain paragraph (null), single-rowDesign rationale
Precision is intentionally approximate for lists and code — the primary consumer is AI feedback loops where ±1 line is acceptable. The goal is to avoid exporting
L1–L80for an 80-line code block when the user selected line 42.