feat: rhwpDev 디버깅 툴킷 — showAllIds / search / findNearest (closes #449)#602
feat: rhwpDev 디버깅 툴킷 — showAllIds / search / findNearest (closes #449)#602oksure wants to merge 2 commits intoedwardkim:develfrom
Conversation
서드파티 앱 연동 시 activeId 매핑 실패 디버깅을 위한 콘솔 API: - rhwpDev.showAllIds(page?) — 렌더링 영역에 pi 오버레이 표시 - rhwpDev.hideAllIds() — 오버레이 제거 - rhwpDev.search(text) — 텍스트 → section/para/offset 역추적 - rhwpDev.findNearest(id, page?) — 유효하지 않은 ID에 가장 가까운 ID 제안 - rhwpDev.help() — 사용법 안내 window.rhwpDev 로 전역 노출 (모든 모드).
There was a problem hiding this comment.
Pull request overview
This PR adds a global window.rhwpDev debugging toolkit to the rhwp-studio frontend so third-party integrators can inspect rendered paragraph IDs and troubleshoot activeId ↔ DOM mapping failures.
Changes:
- Added a new
rhwp-studio/src/core/rhwp-dev.tsmodule withshowAllIds,hideAllIds,search,findNearest, andhelp. - Initialized the toolkit from
rhwp-studio/src/main.tsusing the existingWasmBridgeinstance. - Exposed the toolkit in all modes for integration/debugging workflows.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| rhwp-studio/src/main.ts | Wires the new debugging toolkit into app startup. |
| rhwp-studio/src/core/rhwp-dev.ts | Implements the global debugging helpers that consume WASM text/layout APIs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| showAllIds(pageNum?: number): void { | ||
| removeOverlay(); | ||
| const container = createOverlayContainer(); | ||
| const totalPages = wasm.getPageCount(); |
| const pageEls = document.querySelectorAll(`[data-page="${p}"]`); | ||
| const pageEl = pageEls[0] as HTMLElement | undefined; | ||
| if (!pageEl) continue; |
| const offsetY = pageRect.top - scrollRect.top + getScrollContainer()!.scrollTop; | ||
|
|
||
| for (const run of data.runs) { | ||
| const label = `s${run.section ?? '?'}:pi=${run.para ?? '?'}`; |
| if (!result) { | ||
| console.warn(`[rhwpDev] search("${text}"): not found`); | ||
| return null; | ||
| } | ||
| const pos = result as any; |
| const out: SearchResult = { | ||
| section: pos.section ?? 0, | ||
| paragraph: pos.paragraph ?? 0, | ||
| charOffset: pos.charOffset ?? 0, | ||
| page: pos.page ?? 0, | ||
| x: pos.x ?? 0, | ||
| y: pos.y ?? 0, | ||
| }; | ||
| console.log(`[rhwpDev] search("${text}"): s${out.section}:pi=${out.paragraph} offset=${out.charOffset} page=${out.page}`); |
| }, | ||
|
|
||
| findNearest(targetId: number, pageNum?: number): { id: number; distance: number; text: string } | null { | ||
| const totalPages = wasm.getPageCount(); |
|
|
||
| let nearest: { id: number; distance: number; text: string } | null = null; | ||
| for (const run of data.runs) { | ||
| const id = run.para as number; |
| const pageRect = pageEl.getBoundingClientRect(); | ||
| const scrollRect = getScrollContainer()!.getBoundingClientRect(); | ||
| const offsetX = pageRect.left - scrollRect.left + getScrollContainer()!.scrollLeft; | ||
| const offsetY = pageRect.top - scrollRect.top + getScrollContainer()!.scrollTop; | ||
|
|
…ayout)
- wasm.getPageCount() → wasm.pageCount (getter)
- searchText 반환: { found: boolean, sec, para, charOffset, length }
- getPageTextLayout 필드: secIdx/paraIdx/charStart (not section/para)
- showAllIds: DOM 오버레이 대신 console.table (canvas 렌더러에 data-page 속성 부재)
- findNearest: paraIdx 필드 사용
- 줌 스케일링 이슈 회피 (DOM 오버레이 제거로 해소)
|
Addressed all 8 review comments in 07139be:
Canvas 위 시각적 오버레이가 필요하면 별도 overlay canvas layer를 CanvasView에 추가하는 방향으로 후속 구현 가능합니다. |
v0.7.9 후속 patch 사이클 (5/4 ~ 5/6). ## 신규 기능 - **CLI 바이너리 릴리즈** (Issue #608/#612, @almet 의 요청) - 4 플랫폼 GitHub Release 자산 첨부 (Linux x86_64 / macOS x86_64+aarch64 / Windows x86_64) + SHA-256 체크섬 - **PNG raster backend** (PR #599, @seo-rii) — render P4 단계 - native Skia 기반 PageLayerTree → PNG export, native-skia feature gate - **AI 파이프라인 + VLM 연동 도입** (메인테이너 후속 정정): - --vlm-target claude (1568 longest edge / 1.15 MP, Claude Vision 정합) - --scale / --max-dimension (자동 scale 계산) - export-png CLI 명령 + 매뉴얼 (한글 + 영문 dual) - 한글 폰트 fallback chain + char 단위 fallback (공백 두부 정정) + --font-path 동적 로딩 ## 외부 PR cherry-pick (13 PR / 7 컨트리뷰터) - @planet6897 / Jaeook Ryu (협업): PR #587/#589/#561/#564/#570/#575/ #580/#584/#592/#593/#567 - @oksure (Hyunwoo Park): PR #600 (closes #513) - @seo-rii: PR #599 (refs #536) - @cskwork / @johndoekim / @nameofSEOKWONHONG / @jangster77 — 사이클 누적 ## 메인테이너 정정 Skia 폰트 영역 5개 정정 (한글 fallback / font-path / char-fallback / VLM 옵션 / export-png CLI). ## 인프라 - CI 빌드 안정성 (Cargo.toml [[example]] required-features) - 광범위 페이지네이션 회귀 sweep 도구 (164 fixture / 1,614 페이지 자동) ## 후속 이슈 - #613 (VLM 프리셋 확장) - #614 (DPI 메타데이터) - #615 (pua_oldhangul.rs U+F53A 한컴 정합) - #598 (rhwp-studio 각주 삭제, 외부 컨트리뷰터 공개) ## 잔여 PR (v0.7.11 후속 patch) PR #601, #602 (@oksure) / PR #607 (@dicebattle) / PR #609 (@jangster77, Task #604) / PR #611 (@kihyunnn). 상세: CHANGELOG.md (한글) / CHANGELOG_EN.md (영문).
|
@oksure 님 7번째 사이클 PR 정합 — cherry-pick 머지 완료 (devel 처리 결과
Copilot 자체 검토 응답 정합 (100%)마지막 commit
Issue #449 본질 영역 커버리지 (~85%)
후속 권유정식 시각 오버레이 구현 — canvas 위 overlay div 또는 Canvas API 직접 그리기. 본 영역 후속 PR 환영합니다. 처리 보고서: Issue #449 assignee 정합 ( 활발한 컨트리뷰터의 7번째 PR 흡수 — 감사합니다 🙏 |
|
@oksure 님 — 본 PR cherry-pick 머지 후 메인테이너 시각 판정 게이트웨이 검증 영역에서 본질 결함 두 건이 식별되어 안내드립니다. 본 PR 자체는 close 유지하되, Issue #449 를 reopen 하여 후속 PR 영역 분리합니다. 메인테이너 판정 게이트웨이 방식 (참고용)본 환경 PR 처리는 결정적 검증 + 권위 자료 시각 판정의 2 단계 게이트웨이로 진행합니다:
본 PR 의 권위 게이트웨이: 본질 결함 두 건 (게이트웨이 검증에서 식별)결함 #1: paragraph 식별 부정확 (본문 vs 표/글상자 내부)검증:
현재 동작: rhwpDev.showAllIds(0) 결함 본질: `getPageTextLayout` 의 `runs` 배열은 본문 + 표/글상자 내부 paragraph 를 모두 평탄화 하여 반환. `secIdx`/`paraIdx` 키만 사용 시 본문 paragraph 0 과 셀 내부 paragraph 0 가 같은 키 (`0:0`) 로 충돌 → `showAllIds` 가 본문 paragraph 첫 텍스트 (" * 사업계획서...") 를 표시하지 않고 셀 내부 첫 paragraph 의 "※ " 만 표시. AI activeId 매핑 디버깅 본질에서 부적합: AI 가 `activeId=11` 등 본문 paragraph 를 가리킬 때 셀 내부 paragraph 와 구분 안 되면 매핑 실패 진단 자체가 오도 (Issue #449 의 "표/글상자 내부 등 DOM 깊은 곳" 영역과 정확히 충돌). 개선 영역 제안:
결함 #2: 다중 매치 미처리 (단일 매치만 반환)현재 동작: 결함 본질: `wasm.searchText` 는 첫 매치만 반환. "사업계획" 이 본문 paragraph 0 ("사업계획서") + 표 내부 다수 위치에 등장 시 첫 위치만 표시. AI activeId 매핑 디버깅 본질에서 부적합: 키워드 일치 후보가 여럿일 때 메인테이너/외부 개발자가 모든 후보를 보고 정확한 ID 식별 (또는 "AI 가 잘못된 후보를 골랐는지" 판정) 필요 (Issue #449 의 "AI 환각/매핑 오류 시 Fallback 용도" 영역과 직접 연관). 개선 영역 제안:
본 환경 cherry-pick 결과 (참고)본 PR 의 회귀 0 영역 + 정합 영역 (search 단일 매치 + findNearest distance 추천) 은 cherry-pick 머지 유지. 본문 vs 셀 내부 paragraph 식별 + 다중 매치 영역은 위 두 결함 영역으로 후속 PR 영역 분리. 후속 PR 권유위 두 결함 영역 정정 + 다음 본 PR 의 자체 게이트웨이 검증 권유 (메인테이너 판정 게이트웨이 방식 정합):
본 환경 직접 점검 없이 컨트리뷰터 fork 에서 자체 게이트웨이 검증 후 후속 PR 등록 환영. `feedback_per_task_pr_branch` 정합 — 후속 PR 은 별도 fork branch (`oksure:contrib/rhwpdev-toolkit-v2` 등) 권장. 게이트웨이 영역 식별 가치 본 PR 의 흡수 영역 — 감사합니다 🙏 |
- mydocs/pr/archives/pr_602_review.md (검토 보고서) - mydocs/pr/archives/pr_602_report.md (처리 보고서) - mydocs/orders/20260507.md PR #602 행 추가 (다섯 번째 처리 PR) - rhwp-studio/package-lock.json (본 환경 npm install 결과 정합) PR 처리 본질: - 활발한 컨트리뷰터 @oksure 7번째 PR — 2 commits 보존 cherry-pick 머지 - Docker WASM 재빌드 v0.7.10 (본 환경 v0.6.0 → v0.7.10, renderPageToCanvasFiltered 부재 결함 동시 해소) - 메인테이너 권위 자료 (samples/aift.hwp) 게이트웨이 검증에서 본질 결함 두 건 식별: - 결함 #1: paragraph 식별 부정확 (본문 vs 표/글상자 내부) - 결함 #2: 다중 매치 미처리 - PR #602 close 유지 + Issue #449 reopen + 컨트리뷰터에게 메인테이너 판정 게이트웨이 방식 + 후속 PR 자체 검증 영역 안내 메인테이너 판정 게이트웨이 방식의 권위 사례 — 결정적 검증만으로는 본질 결함 식별 부족, 권위 자료 시각 판정에서 결함 식별 + 컨트리뷰터에게 게이트웨이 방식 + 자체 검증 패턴 안내.
PR #684 cherry-pick 결과 영역에서 main.ts 영역의 initRhwpDev 영역 import 영역 중복 영역 발생 영역 — 본 환경 영역의 PR #602 영역 결과 (line 28 import + line 38-40 외부 호출 영역) 와 PR #684 영역의 c72e5e5 commit 영역 (initialize() 함수 안 DEV 게이트 영역 안 호출 영역) 영역 동시 영역 존재 영역 → TypeScript TS2300 영역 에러 영역. PR #684 의 본질 영역 정합 영역으로 line 38-40 영역 제거: - line 28 영역 import 영역 유지 (본 환경 PR #602 영역 결과) - line 38-40 영역의 외부 호출 영역 제거 (PR #684 의 의도 영역 — initialize() 안 DEV 게이트 영역 안 호출 영역만 활성 영역) - line 99-100 영역의 if (import.meta.env.DEV) { initRhwpDev(wasm); } 영역 유지 (PR #684 c72e5e5 영역 결과) 검증: - npm run build TypeScript 타입 체크 + dist 빌드 통과 (index-21tD9d3W.js 691,386) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
목적
서드파티 애플리케이션에서 rhwp 렌더링 뷰어와 연동 시, AI가 제공한
activeId가 DOM에 없거나 찾지 못하는 매핑 실패 이슈 디버깅 지원.구현 내용
window.rhwpDev전역 객체 (모든 모드에서 활성):showAllIds(page?)hideAllIds()search(text)findNearest(id, page?)help()사용 예시
파일 변경
rhwp-studio/src/core/rhwp-dev.ts— 신규 (디버깅 툴킷 모듈)rhwp-studio/src/main.ts—initRhwpDev(wasm)호출 추가검증
npx tsc --noEmit: 기존 chrome 타입 에러 외 신규 에러 없음getPageTextLayout/searchTextAPI 기반 구현참고
getPageTextLayout반환 형식에 따라 오버레이 정확도가 달라질 수 있음 — 피드백 후 조정 가능이 방향이 적절한지 피드백 부탁드립니다.