# Page Clipping + Highlight Implementation Plan

## Goal
- 사용자가 특정 페이지에서 선택한 텍스트를 클리핑(저장)한다.
- 저장된 클립은 원문 위치에 하이라이트로 다시 표시된다.
- 팝업에서 클립 목록을 보고 해당 위치로 다시 이동할 수 있다.

## Scope (v1)
1. 지원 대상
- 텍스트 기반 웹페이지 (`contenteditable` 제외, 일반 DOM 문서 우선)
- 탭 단위 클립 저장/조회

2. 포함 기능
- 선택 텍스트 캡처
- 하이라이트 주입/복원
- 클립 목록 조회/삭제
- 클릭 시 원문 위치로 스크롤

3. 제외 기능(후속)
- PDF/캔버스/이미지 OCR 하이라이트
- 협업 공유/서버 동기화
- 다중 색상 태깅, 폴더 분류

## Data Model (Draft)
```ts
type ClipItem = {
  id: string
  tabId?: number
  pageUrl: string
  pageTitle: string
  quote: string
  createdAt: string
  color: 'yellow'
  anchor: {
    textStart: string
    textEnd: string
    exact: string
    prefix?: string
    suffix?: string
    xpathStart?: string
    xpathEnd?: string
    startOffset?: number
    endOffset?: number
  }
}
```

## Architecture
1. Content Script
- 사용자 선택(`window.getSelection`)에서 `Range` 추출
- `anchor` 생성(텍스트 인용 + DOM 포지션)
- background에 `clip:create` 메시지 전송
- `clip:apply` 이벤트 수신 시 하이라이트 렌더링

2. Background (Service Worker)
- `clip:create`, `clip:list`, `clip:delete`, `clip:reveal` 메시지 처리
- `storage.local` 기반 영속화
- 탭 활성화/페이지 완료 시 `clip:sync` 트리거

3. Popup/History UI
- 현재 탭 URL 기준 클립 목록 요청
- 항목별 `위치로 이동`, `삭제` 버튼
- 상태 메시지(저장 성공/실패) 표시

## Step-by-Step
1. Step 1: Selection Capture + Overlay
- `src/lib/clipAnchor.ts` 생성
- `Range -> anchor` 변환 유틸 구현
- `src/content/index.ts`에 단축키/우클릭 기반 캡처 진입점 추가
- `span[data-gomdown-clip]` 하이라이트 렌더링/해제 로직 구현

2. Step 2: Store + Message Channel
- `src/lib/clipStore.ts` 생성 (`list/upsert/delete/byUrl`)
- background message router에 `clip:*` 타입 추가
- dedupe(`pageUrl + exact + createdAt window`) 정책 추가

3. Step 3: Popup UI
- `src/popup/main.tsx`에 "Clips" 섹션 추가
- 현재 탭 URL 클립 조회 + 목록 렌더링
- `Reveal/Delete` 액션과 오류 상태 처리

4. Step 4: Re-anchoring
- 페이지 로드 시 `clip:list` 후 순차 복원
- 우선순위:
- `exact + prefix/suffix` 텍스트 매칭
- 실패 시 `xpath + offset` 복구
- 둘 다 실패 시 `broken anchor`로 표시

5. Step 5: Export/Import + QA
- JSON export/import 메시지 추가
- 샘플 페이지(뉴스, 블로그, SPA) 수동 테스트
- 회귀 체크리스트 문서화

## QA Checklist
- 같은 페이지 새로고침 후 하이라이트가 유지된다.
- SPA 라우팅(YouTube/블로그) 후에도 복원 시도가 동작한다.
- 원문 DOM이 일부 바뀐 경우, 텍스트 매칭 fallback이 동작한다.
- 클립 삭제 시 화면/저장소에서 모두 제거된다.
- 확장 비활성화 상태에서 캡처가 차단된다.

## Risk & Mitigation
1. DOM 변형으로 앵커 붕괴
- 텍스트 인용 앵커 + XPath 이중 저장

2. 성능 저하(클립 다수)
- URL 단위 lazy apply, viewport 근처 우선 렌더

3. 사이트 충돌(CSS/스크립트)
- 고유 data-attribute와 최소 침습 스타일 사용

## Definition of Done
- 사용자는 텍스트 선택 후 1회 액션으로 클립 저장 가능
- 같은 URL 재방문 시 하이라이트 자동 복원
- 팝업에서 클립 조회/이동/삭제 가능
- 크롬 기준 수동 시나리오 10개 중 9개 이상 성공
