Feat/outline anchor #31

Merged
hyungi merged 2 commits from feat/outline-anchor into main 2026-06-08 21:16:45 +09:00

2 Commits

Author SHA1 Message Date
hyungi 5c065e6bec feat(documents): 개요 점프 결선 — anchor splice + id↔id 점프 + scroll-spy ([id])
불만② 개요→본문 점프를 deterministic 하게 결선(경로 A). 상세페이지([id], 개요 rail 보유).

- MarkdownDoc: anchorMap prop 추가 → 렌더 전 md_content 의 각 offset(내림차순)에
  <span id="sec-{chunkId}" class="md-anchor"> splice(점프 타깃). DOMPurify span+id+class 통과.
- SectionOutline: onJump(chunkId)/activeKey prop. 클릭=아코디언 toggle + onJump(점프).
  activeKey 일치 항목 좌측 accent border 강조(scroll-spy).
- [id]: anchorMap=buildAnchorMap(md_content, sections)(canShowMarkdown 시) → MarkdownDoc 전달.
  jumpToSection=#sec-id scrollIntoView. scroll-spy(window scroll, 120px 상단 통과 마지막 anchor).
  SectionOutline 양쪽(xl rail·details)에 onJump/activeKey 배선.

id↔id 직매칭이라 중복제목(표-1·Part UW 814건)·비-ATX(제N조) 정확. anchor 없는 절=점프
비활성(아코디언 폴백). node test 10/10, vite build + lint:tokens(신규0) PASS.
다음 = 3-pane(DocumentViewer) 개요 rail(commit 3, 레이아웃).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 20:17:07 +09:00
hyungi e1a047c2c2 feat(documents): 개요 점프 anchorMap 유틸 (forward-cursor 3중 방어)
불만② 개요→본문 점프의 deterministic anchor 좌표 산출(경로 A, FE-only).
게이트 측정상 textContent 매칭은 중복 63%·비-ATX 로 5% + silent 오점프 → md_content
에서 각 절 heading 라인 offset 을 찾아 <a id="sec-{chunk_id}"> 주입 좌표를 만든다.

★ false-early-match 방어 3중 (적대 리뷰 반영):
- 라인-시작(전체-라인) 매칭 → 본문 중간 상호참조("see Part UW")는 라인 전체가 제목과
  같지 않아 제외(forward-cursor 가 못 막던 핵심 구멍).
- 전체 매칭 + truncation(builder [:200]) 처리 → '제1조'가 '제1조의2' 오매칭 차단.
- 단조 커서 + 코드펜스 회피 → 역행/펜스 매칭 거부 = anchor 없음(점프 비활성, 오점프 금지).

window/section_split 조각·빈 제목은 skip. node test 10/10 PASS(상호참조 선행·중복 단조·
prefix·평문 제N조·펜스·window·miss·heading_path fallback). 순수 함수, vite build PASS.
다음 commit = MarkdownDoc splice + SectionOutline 점프 + DocumentViewer rail/scroll-spy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 20:11:00 +09:00