fix: Ctrl+N,M 수식 단축키 + 수식 삭제 오류 수정 (closes #767, closes #766)#786
fix: Ctrl+N,M 수식 단축키 + 수식 삭제 오류 수정 (closes #767, closes #766)#786oksure wants to merge 2 commits into
Conversation
…edwardkim#766) 1. chordMapN에 'm'/'ㅡ' → 'insert:equation' 매핑 추가 (edwardkim#767) - Ctrl+N 후 M 키 입력 시 브라우저 새 창 대신 수식 삽입 동작 2. 수식 객체 Backspace/Delete 삭제 시 "Shape이 아닙니다" 오류 수정 (edwardkim#766) - deleteEquationControl WASM API 신규 추가 - 키보드 핸들러 삭제 디스패치에 equation 분기 추가 - input-handler, input-handler-keyboard, input-handler-picture, insert commands 모두 equation 분기 추가
There was a problem hiding this comment.
Pull request overview
수식 입력 단축키(Ctrl+N,M) 매핑 누락을 보완하고, 수식 컨트롤이 선택된 상태에서 Backspace/Delete/Cut으로 삭제할 때 Shape 삭제 경로로 잘못 디스패치되던 오류를 수정하기 위한 PR입니다.
Changes:
Ctrl+N코드 단축키(chord) 맵에m/ㅡ→insert:equation매핑 추가- Rust/WASM에
deleteEquationControlAPI 추가 및 Studio 측 브리지 래퍼 추가 - Studio 키보드/컷/오브젝트 삭제 경로들에
ref.type === 'equation'분기 추가
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
src/wasm_api.rs |
WASM export deleteEquationControl 추가 |
src/document_core/commands/object_ops.rs |
delete_equation_control_native 구현 추가 |
rhwp-studio/src/core/wasm-bridge.ts |
deleteEquationControl() TS 래퍼 추가 |
rhwp-studio/src/engine/input-handler-keyboard.ts |
chordMapN에 수식 단축키 추가 및 키보드 삭제/컷 경로에 equation 분기 추가 |
rhwp-studio/src/engine/input-handler.ts |
cutObject 처리에서 equation 삭제 분기 추가 |
rhwp-studio/src/engine/input-handler-picture.ts |
deleteObjectControl에서 equation 삭제 분기 추가 |
rhwp-studio/src/command/commands/insert.ts |
object:delete에서 equation 삭제 분기 추가 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// 수식(Equation) 컨트롤을 문단에서 삭제한다. | ||
| pub fn delete_equation_control_native( | ||
| &mut self, | ||
| section_idx: usize, | ||
| parent_para_idx: usize, | ||
| control_idx: usize, | ||
| ) -> Result<String, HwpError> { | ||
| if section_idx >= self.document.sections.len() { | ||
| return Err(HwpError::RenderError(format!("구역 인덱스 {} 범위 초과", section_idx))); | ||
| } | ||
| let section = &mut self.document.sections[section_idx]; | ||
| if parent_para_idx >= section.paragraphs.len() { | ||
| return Err(HwpError::RenderError(format!("문단 인덱스 {} 범위 초과", parent_para_idx))); | ||
| } | ||
| let para = &mut section.paragraphs[parent_para_idx]; | ||
| if control_idx >= para.controls.len() { | ||
| return Err(HwpError::RenderError(format!("컨트롤 인덱스 {} 범위 초과", control_idx))); | ||
| } | ||
| if !matches!(¶.controls[control_idx], Control::Equation(_)) { | ||
| return Err(HwpError::RenderError("지정된 컨트롤이 수식이 아닙니다".to_string())); | ||
| } |
| para.char_count -= 8; | ||
| } | ||
|
|
||
| Self::reflow_paragraph_line_segs_after_control_delete(para, &self.styles, self.dpi); |
| /// 수식 컨트롤을 문단에서 삭제한다. | ||
| /// | ||
| /// 반환: JSON `{"ok":true}` | ||
| #[wasm_bindgen(js_name = deleteEquationControl)] | ||
| pub fn delete_equation_control( | ||
| &mut self, | ||
| section_idx: u32, | ||
| parent_para_idx: u32, | ||
| control_idx: u32, | ||
| ) -> Result<String, JsValue> { | ||
| self.delete_equation_control_native( | ||
| section_idx as usize, | ||
| parent_para_idx as usize, | ||
| control_idx as usize, | ||
| ) | ||
| .map_err(|e| e.into()) | ||
| } |
| deleteEquationControl(sec: number, para: number, ci: number): { ok: boolean } { | ||
| if (!this.doc) throw new Error('문서가 로드되지 않았습니다'); | ||
| return JSON.parse(this.doc.deleteEquationControl(sec, para, ci)); |
| if (ref.type === 'image') { | ||
| wasm.deletePictureControl(ref.sec, ref.ppi, ref.ci); | ||
| } else if (ref.type === 'equation') { | ||
| wasm.deleteEquationControl(ref.sec, ref.ppi, ref.ci); |
| if (ref.type === 'image') { | ||
| wasm.deletePictureControl(ref.sec, ref.ppi, ref.ci); | ||
| } else if (ref.type === 'equation') { | ||
| wasm.deleteEquationControl(ref.sec, ref.ppi, ref.ci); |
| if (ref.type === 'image') { | ||
| wasm.deletePictureControl(ref.sec, ref.ppi, ref.ci); | ||
| } else if (ref.type === 'equation') { | ||
| wasm.deleteEquationControl(ref.sec, ref.ppi, ref.ci); |
| if (ref.type === 'image') { | ||
| wasm.deletePictureControl(ref.sec, ref.ppi, ref.ci); | ||
| } else if (ref.type === 'equation') { | ||
| wasm.deleteEquationControl(ref.sec, ref.ppi, ref.ci); |
| export function deleteObjectControl(this: any, ref: { sec: number; ppi: number; ci: number; type: 'image' | 'shape' | 'equation' | 'group' | 'line' }): void { | ||
| if (ref.type === 'shape' || ref.type === 'group' || ref.type === 'line') { | ||
| this.wasm.deleteShapeControl(ref.sec, ref.ppi, ref.ci); | ||
| } else if (ref.type === 'equation') { | ||
| this.wasm.deleteEquationControl(ref.sec, ref.ppi, ref.ci); | ||
| } else { | ||
| this.wasm.deletePictureControl(ref.sec, ref.ppi, ref.ci); |
| if (ref.type === 'shape' || ref.type === 'line' || ref.type === 'group') { | ||
| services.wasm.deleteShapeControl(ref.sec, ref.ppi, ref.ci); | ||
| } else if (ref.type === 'equation') { | ||
| services.wasm.deleteEquationControl(ref.sec, ref.ppi, ref.ci); |
Copilot 리뷰 반영: 수식 삭제 후 남은 컨트롤 높이 계산에서 Control::Equation 분기 누락 → 수식만 남은 문단의 line_segs가 0으로 리셋되는 가능성 수정. 참고: 셀 내 수식 삭제(cellIdx/cellParaIdx 전달)는 현재 deleteEquation의 스코프 밖 — 본문 수식 삭제만 지원.
|
Copilot 리뷰 피드백 반영 (b376a0d): reflow 높이 계산 수정: 셀 내 수식 삭제 (cellIdx/cellParaIdx): 현재 |
PR #786 영역 chordMapN['m'] / ['ㅡ'] 매핑 정정 영역 영역 chord 2번째 키 영역만 처리. 그러나 chord 1번째 키 (Ctrl+N) 영역 영역 InputHandler textarea keydown listener 영역 영역만 차단 — textarea 미포커스 상태 (메뉴 바 / button 클릭 후 등) 영역 영역 keydown 영역 document 발동 영역 setupGlobalShortcuts 영역 영역 InputHandler.active 영역 영역 return → Ctrl+N 차단 부재 → 크롬 새 창 발동. 정정: setupGlobalShortcuts 영역 영역 InputHandler 활성 시점 영역 영역도 Ctrl+N 차단 추가: - e.preventDefault() (크롬 새 창 차단) - inputHandler._pendingChordN = true (chord 1번째 키 활성화) - inputHandler.focus() (textarea 포커스 복귀 — 후속 키 영역 InputHandler chord 2번째 키 처리) 작업지시자 시각 검증 영역 영역 발견: "수식 객체 삭제 통과. Ctrl+N 누르면 크롬 웹브라우저 단축키가 먼저 발동." PR #740 자기 정정 패턴 정합 — devel HEAD 잠재 결함 영역 영역 본 PR 의 신규 호출 영역 영역 노출 영역 자기 정정 commit.
This reverts commit 7bc2dc0.
…cut 회피) PR #786 영역 chordMapN['m'] / ['ㅡ'] 매핑 정정 영역 영역 chord 2번째 키 영역만 처리. 그러나 Chrome / Edge 영역 영역 Ctrl+N (새 창) 영역 영역 OS-level reserved shortcut 영역 영역 JS preventDefault() 차단 불가 영역 영역 chord 1번째 키 영역 영역 자체 발동 부재. 작업지시자 결정: chord 키 영역 영역 Ctrl+N → Ctrl+M 변경. 정정 영역: - input-handler-keyboard.ts: chordMapN → chordMapM, _pendingChordN → _pendingChordM, chord 1번째 키 영역 영역 'm'/'M'/'ㅡ' (Ctrl+M) - insert.ts: shortcutLabel 'Ctrl+N,M' → 'Ctrl+M,M' (수식) - table.ts: shortcutLabel 'Ctrl+N,F' → 'Ctrl+M,F' (계산식) - edit.ts: shortcutLabel 'Ctrl+N,K' → 'Ctrl+M,K' (누름틀 고치기) - page.ts: shortcutLabel 'Ctrl+N,S' → 'Ctrl+M,S' (감추기) 자기 정정 commit (7bc2dc0, setupGlobalShortcuts Ctrl+N chord 시작 보강) revert 영역 영역 fb1a22c 머지 — 효과 없는 정정 영역 영역 정합성 영역 영역 보존. 작업지시자 시각 검증 영역 영역 발견 (PR #786 후속): "Ctrl+N 누르면 크롬 웹브라우저 단축키가 먼저 발동." 본질: Chrome reserved shortcut 영역 영역 JS 차단 불가 영역 영역 chord 키 변경 영역 영역 회피. PR #740 자기 정정 패턴 정합.
작업지시자 시각 검증 영역 영역 발견: '한글 IME 상태에서도 적용되어야 합니다.' 본질: 한국어 IME 합성 중 영역 영역 e.key === 'Process' (Chrome 영역 영역 IME 합성 중 영역 영역 일관 영역 영역) 영역 영역 line 201 영역 영역 IME 합성 중 영역 영역 즉시 return → chord 1번째/2번째 키 활성화 부재. 정정 (input-handler-keyboard.ts +18): - chord 1번째 키 영역 영역 IME 합성 중 영역 영역 e.code === 'KeyM' 영역 영역 활성화 - chord 2번째 키 영역 영역 _pendingChordM 활성화 시 e.code 영역 영역 chordMapM lookup (KeyM/KeyN/KeyS/KeyF/KeyK → 'm'/'n'/'s'/'f'/'k') 본 환경 영역 영역 IME 합성 중 영역 영역 chord 1/2번째 키 영역 영역 모두 e.code 영역 영역 판별 영역 영역 한글 IME 상태 영역 영역 정합 동작. PR #740 자기 정정 패턴 정합.
… 오류 수정 PR #739 (수식 신규 입력) 후속 발견 결함 2건 정정 + 본 환경 자기 정정 4건 (Chrome reserved shortcut 회피 + IME 합성 중 chord 활성화). 본 PR cherry-pick (2 commits): - 4a8772b: Issue #767 (Ctrl+N,M 단축키 매핑) + Issue #766 (수식 객체 삭제 오류) 정정 - a86668e: Copilot 리뷰 — reflow_paragraph_line_segs Equation 높이 반영 본 환경 자기 정정 commits (4건): - 7bc2dc0: setupGlobalShortcuts Ctrl+N chord 시작 보강 시도 (Chrome reserved shortcut 영역 영역 효과 없음) - fb1a22c: 7bc2dc0 revert (정합성 회복) - 924ca0f: chord 키 Ctrl+N → Ctrl+M 변경 (작업지시자 결정 — Chrome reserved shortcut 회피) - e906c1b: Ctrl+M chord IME 합성 중 활성화 (한글 IME e.code 판별) 본질 — Chrome / Edge 영역 영역 Ctrl+N (새 창) 영역 영역 OS-level reserved shortcut 영역 영역 JS preventDefault() 차단 불가 영역 영역 chord 키 영역 영역 Ctrl+M 영역 영역 변경. 한글 IME 합성 중 영역 영역 e.key === 'Process' 영역 영역 e.code (KeyM/KeyN/KeyS/KeyF/KeyK) 판별 영역 영역 chord 활성화. 정정 영역: - input-handler-keyboard.ts: chordMapN → chordMapM, _pendingChordN → _pendingChordM, chord 1/2번째 키 영역 영역 Ctrl+M + IME 합성 중 e.code 판별 - shortcutLabel: Ctrl+N,? → Ctrl+M,? (insert/table/edit/page) - delete_equation_control_native + WASM export deleteEquationControl 신규 - 키보드 핸들러 4개소 영역 'equation' 분기 추가 검증: - cargo build/test/clippy --release ALL GREEN - tsc --noEmit ✅ - 광범위 sweep 170/170 same - WASM 4.68 MB 재빌드 - 작업지시자 웹 에디터 시각 검증 ✅ 통과 (수식 객체 삭제 + Ctrl+M,M 영문/한글 IME) closes #767 + #766
|
@oksure 검토 완료했습니다. 감사합니다. 처리 결과Merge commit: 본 PR 본질PR #739 (수식 신규 입력) 후속 발견 결함 2건 정정:
본 환경 자기 정정 (4 commits)작업지시자 웹 에디터 시각 검증 영역 영역 발견된 결함 영역 영역 본 환경 자기 정정:
shortcutLabel 갱신: Ctrl+N,M → Ctrl+M,M (수식) / Ctrl+N,F → Ctrl+M,F (계산식) / Ctrl+N,K → Ctrl+M,K (누름틀 고치기) / Ctrl+N,S → Ctrl+M,S (감추기). 검증
5/11 사이클 1번째 PR — 수고하셨습니다. |
|
Merged. Merge commit: ea9531d |
PR #786 (closes #767+#766) — PR #739 후속 발견 결함 정정 + 본 환경 자기 정정 4 commits (Chrome reserved shortcut 회피 영역 chord 키 Ctrl+N → Ctrl+M 변경 + IME 합성 중 chord 활성화). Merge commit: ea9531d Cherry-pick: 4a8772b + a86668e 자기 정정: 7bc2dc0 (revert 7bc2dc0 → fb1a22c) + 924ca0f (chord Ctrl+N→Ctrl+M) + e906c1b (IME 합성 중 chord) 5/11 사이클 시작 — orders/20260511.md 신규 등록 (5/10 사이클 27 PR 후 첫 PR).
5/10 + 5/11 사이클 누적 — 외부 기여자 다수 PR 30+ 머지. Cargo.toml + rhwp-vscode/package.json + npm/editor/package.json + rhwp-studio/package.json: 0.7.10 → 0.7.11 rhwp-vscode/CHANGELOG.md: [0.7.11] 항목 추가 핵심 변경: - Skia native raster P8 (#761) + P9 (#769) — Layer IR contract hardening + text replay parity - HWP3 native 렌더링 (#753) — hwp3-sample10 8 단계 정정 + Git LFS pdf-large/ 신규 - 페이지네이션 정정 (#778) — Task #703 다단 컬럼 분배 회귀 정정 - rhwp-studio 인터랙션 (PR #781/#786/#787/#788) — scrollbar/수식/표 셀/도구 모음 결함 정정 - rhwp-studio editor 신규 기능 (PR #728/#748/#750/#760 등) — 표 편집 Undo/Redo + 다단 설정 + 다수 단축키
요약
PR #739 (수식 신규 입력) 후속 버그 2건 수정:
1. Ctrl+N,M 단축키 매핑 누락 (#767)
chordMapN에m/ㅡ(한글 IME) →insert:equation매핑 추가.기존: Ctrl+N 후 M 입력 시
chordMapN['m']미발견 →preventDefault()미호출 → 브라우저 기본 동작(새 창).2. 수식 객체 Backspace/Delete 삭제 오류 (#766)
수식 객체 선택 후 Backspace 시
deleteShapeControl호출 →Control::Equation타입 불일치로 "Shape이 아닙니다" 오류.수정 내용:
delete_equation_control_native+ WASM exportdeleteEquationControl신규ref.type === 'equation'분기 추가:input-handler-keyboard.ts(Backspace, Ctrl+X, Ctrl+X in Ctrl handler)input-handler.ts(cut handler)input-handler-picture.ts(deleteObjectControlhelper)command/commands/insert.ts(object:delete command)wasm-bridge.ts에deleteEquationControlwrapper 추가검증
cargo test --release✅ ALL GREENcargo clippy -- -D warnings✅ 경고 없음tsc --noEmit✅ (기존 @wasm 모듈 에러 외 신규 없음)감사합니다.