Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions mydocs/orders/20260506.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 오늘 할일 - 2026년 5월 6일

## M100 — v1.0.0 조판 엔진 체계화

| Issue | 타스크 | 상태 | 비고 |
|------|--------|------|------|
| #598 | rhwp-studio 각주 삭제 2차: 본문 각주 삭제 API/UI | 완료 | PR #642 open 전 e2e/요구사항 점검 완료 |
172 changes: 172 additions & 0 deletions mydocs/plans/task_m100_598.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Task #598 수행 계획서 — 각주 삭제 1차: 본문 각주 마커 hit test + 커서 이동 정합

## 이슈 정합

- **Issue**: [#598](https://github.com/edwardkim/rhwp/issues/598) — rhwp-studio: 각주 삭제 기능 구현
- **마일스톤**: M100 — v1.0.0 조판 엔진 체계화
- **작업 브랜치**: `local/task598`
- **기준 브랜치**: `upstream/devel`
- **기준 커밋**: `9b49063`
- **대표 샘플**: `samples/footnote-01.hwp`
- **1차 작업 범위**: 본문 각주 마커 hit test + 좌우 커서 이동 단위 정합

## 배경

이슈 #598은 각주 삭제 기능 전체를 다룬다. 그러나 삭제 UX의 전제는 본문 각주 마커가 편집 영역에서 실제 커서 이동 단위로 취급되는 것이다.

현재 코드 기준으로는 다음 기반이 이미 존재한다.

- 각주 삽입 API: `insert_footnote_native`, `WasmBridge.insertFootnote()`, `insert:footnote`
- 각주 영역 내부 hit test/edit API: `hitTestFootnote`, `hitTestInFootnote`, `getCursorRectInFootnote`, `getPageFootnoteInfo`
- 본문 렌더링의 각주 마커 노드: `RenderNodeType::FootnoteMarker`

반면 본문 커서 이동 및 hit test에는 각주 마커가 아직 한컴 정합의 1칸 단위로 편입되어 있지 않다. 따라서 1차 작업은 삭제 API/UI 구현 전에 본문 각주 마커를 클릭/방향키 대상으로 만드는 데 집중한다.

## 사전 분석

### 1. 본문 렌더링에는 각주 마커 bbox가 있다

`src/renderer/layout/paragraph_layout.rs` 는 문단 내 각주 위치에 `FootnoteMarkerNode` 를 생성한다. 이 노드에는 `section_index`, `para_index`, `control_index`, `number`, `text` 가 들어 있으므로 본문 마커 hit test API의 반환값을 구성할 수 있다.

### 2. 기존 hit test는 TextRun 중심이다

`src/document_core/queries/cursor_rect.rs` 의 일반 `hit_test_native` 는 주로 `TextRun` 을 수집해 문자 위치를 반환한다. 본문 `FootnoteMarker` 노드는 별도 수집 대상이 아니므로 마커 자체 클릭이 각주 영역 이동으로 연결되지 않는다.

### 3. 커서 이동 길이 계산에서 Footnote가 빠져 있다

`src/document_core/helpers.rs` 의 `navigable_text_len()` 은 Shape/Table/Picture/Equation/CharOverlap 중심으로 보정하며 `Control::Footnote` 를 1칸 단위로 세지 않는다.

`src/document_core/queries/doc_tree_nav.rs` 의 `classify_navigable()` 도 `Control::Footnote` 를 네비게이션 가능한 inline control 로 분류하지 않는다. 이 때문에 좌우 방향키 이동에서 각주 마커 앞/뒤 위치를 안정적으로 만들 수 없다.

## 작업 목표

1차 작업의 완료 기준은 다음과 같다.

- 본문 각주 마커 클릭 시 해당 각주 영역으로 커서가 이동한다.
- 본문 좌우 방향키 이동에서 각주 마커가 1칸 이동 단위로 취급된다.
- 각주 마커 앞/뒤 커서 위치가 Delete/Backspace 삭제 분기를 붙일 수 있는 형태로 안정화된다.
- 기존 각주 영역 내부 편집 동작은 회귀하지 않는다.

## 범위

### 포함

- 본문 `FootnoteMarker` bbox 기반 hit test API 추가
- WasmBridge 본문 각주 마커 hit test 메서드 추가
- 마우스 처리에서 본문 각주 마커 클릭 시 각주 영역 진입 처리
- `Control::Footnote` 를 본문 커서 이동의 1칸 inline unit 으로 반영
- 본문 각주 마커 위치의 cursor rect 계산 보정
- `samples/footnote-01.hwp` 기반 수동/자동 검증
- 가능하면 rhwp-studio e2e에 hit test 및 좌우 이동 회귀 테스트 추가

### 제외

- 각주 삭제 WASM API 구현
- Delete/Backspace 삭제 분기
- 삭제 확인 다이얼로그
- 삭제 Undo/Redo
- 표 셀/글상자 내부 각주 삭제 UX 전면 구현
- 미주 삭제 기능

## 의심 코드 영역

| 영역 | 파일 | 검토 포인트 |
|------|------|-------------|
| 본문 hit test | `src/document_core/queries/cursor_rect.rs` | `FootnoteMarker` 수집 및 bbox hit API 추가 |
| 렌더 노드 | `src/renderer/render_tree.rs` | `FootnoteMarkerNode` 메타데이터 재사용 가능성 확인 |
| 본문 마커 생성 | `src/renderer/layout/paragraph_layout.rs` | `control_index` 가 실제 footnote control index 와 정합하는지 확인 |
| 네비게이션 길이 | `src/document_core/helpers.rs` | `Control::Footnote` 를 logical/navigable length 에 포함할지 결정 |
| DFS 이동 | `src/document_core/queries/doc_tree_nav.rs` | `classify_navigable()` 및 forward/backward 이동 규칙 보정 |
| WASM export | `src/wasm_api.rs` | 신규 hit test API 노출 |
| TS 브리지 | `rhwp-studio/src/core/wasm-bridge.ts` | 신규 API JSON 파싱 래퍼 추가 |
| 마우스 처리 | `rhwp-studio/src/engine/input-handler-mouse.ts` | 본문 마커 hit 시 각주 영역 진입 |
| 커서 상태 | `rhwp-studio/src/engine/cursor.ts` | 각주 모드 진입 전 저장 본문 위치와 rect 갱신 확인 |

## 단계 분리 (5 stages)

### Stage 1 — 진단 확정

- `samples/footnote-01.hwp` 에서 본문 각주 마커와 각주 영역 위치를 재현한다.
- `dump-pages`, `dump` 또는 WASM 직접 호출로 footnote source 의 `sec/para/controlIdx` 를 확인한다.
- `FootnoteMarkerNode.control_index` 가 실제 `Control::Footnote` 인덱스와 일치하는지 검증한다.
- 현재 `navigateNextEditable` 좌우 이동이 각주 마커를 건너뛰는 지점을 확인한다.

**산출물**: `mydocs/working/task_m100_598_stage1.md`

### Stage 2 — 구현 계획서 작성

- 본문 마커 hit test API의 반환 JSON 구조를 확정한다.
- 각주 마커를 cursor offset 1칸으로 세는 기준을 확정한다.
- `getCursorRect` 에서 각주 마커 앞/뒤 위치를 어떻게 표현할지 결정한다.
- e2e 검증 방식과 수동 시각 판정 기준을 확정한다.

**산출물**: `mydocs/plans/task_m100_598_impl.md`

### Stage 3 — 1차 구현

- Rust 본문 각주 마커 hit test API 추가
- WASM export 및 `WasmBridge` 래퍼 추가
- `input-handler-mouse.ts` 에 본문 마커 클릭 분기 추가
- `navigable_text_len()` / `navigate_next_editable()` 에 각주 마커 1칸 이동 규칙 반영
- 필요 시 본문 각주 마커 위치의 cursor rect 보정 추가

**산출물**: `mydocs/working/task_m100_598_stage3.md`

### Stage 4 — 검증

- `cargo test`
- `cargo build`
- rhwp-studio 타입/빌드 검증
- `samples/footnote-01.hwp` 수동 검증
- 가능하면 `rhwp-studio/e2e/` 각주 마커 click/arrow 테스트 추가 및 실행

**산출물**: `mydocs/working/task_m100_598_stage4.md`

### Stage 5 — 1차 작업 보고

- 본문 각주 마커 hit test와 좌우 이동 정합 결과 정리
- 2차 작업 범위인 삭제 API/UI의 연결 지점 정리
- 오늘 할일 상태 갱신
- 작업지시자 승인 후 2차 작업 계획으로 이동

**산출물**: `mydocs/working/task_m100_598_stage5.md`

## 검증 게이트

| 검증 | 기준 |
|------|------|
| 본문 마커 클릭 | 클릭한 각주 번호의 각주 영역 커서 위치로 진입 |
| ArrowRight | 각주 앞 위치 → 각주 뒤 위치로 1칸 이동 |
| ArrowLeft | 각주 뒤 위치 → 각주 앞 위치로 1칸 이동 |
| 기존 각주 영역 클릭 | `hitTestFootnote` / `hitTestInFootnote` 기존 동작 유지 |
| `cargo test` | 회귀 0 |
| rhwp-studio e2e | 각주 마커 hit/move 회귀 0 |

## 위험 영역

| 위험 | 가능성 | 회피책 |
|------|--------|--------|
| `control_index` 가 실제 footnote control index 와 불일치 | 중간 | Stage 1 에서 렌더 노드와 IR control 위치를 먼저 대조 |
| `navigable_text_len()` 변경이 표/도형/수식 이동에 회귀 유발 | 중간 | Footnote 전용 조건으로 최소 변경, 기존 inline control 테스트 확인 |
| cursor offset 과 text offset 혼동 | 중간 | logical offset 변환 헬퍼와 기존 `control_text_positions()` 의미를 문서화 후 구현 |
| 각주 영역 내부 hit test 회귀 | 낮음~중간 | 기존 footnote zone API는 수정 최소화 |
| 표 셀/글상자 내부 각주까지 범위 확장 | 중간 | 1차 작업은 body source 를 우선 대상으로 제한하고 후속 범위로 분리 |

## 처리 정합

- 소스 수정은 본 수행계획서 승인 후에도 바로 진행하지 않고, Stage 1 진단 완료보고서와 구현 계획서 승인 이후 진행한다.
- 단계별 완료보고서는 해당 단계 변경과 함께 task 브랜치에서 커밋한다.
- 최종 결과보고서 및 오늘 할일 갱신도 task 브랜치에서 커밋한다.
- 이슈 close 는 작업지시자 승인 후에만 수행한다.

## 승인 게이트

1. 본 수행계획서 승인 → Stage 1 진단 확정 진행
2. Stage 1 완료보고서 승인 → 구현 계획서 작성
3. 구현 계획서 승인 → Stage 3 1차 구현 시작
4. Stage 3/4 완료보고서 승인 → Stage 5 1차 작업 보고
5. 1차 작업 보고 승인 → 2차 삭제 API/UI 작업 계획으로 이동

## 다음 단계

작업지시자 승인 후 Stage 1 진단 확정 진행.
Loading
Loading