라이브 편집 선택·콜아웃·인용 안정화 및 오른쪽 사이드바 여백 보정 (v1.5.70)

Selection Bridge로 블록 간 선택·삭제를 보강하고, 콜아웃·인용 멀티라인 Enter·전체 선택 삭제·한글 IME 문제를 수정했다. Obsidian식 위첨자 문법과 RightSidebar 패딩·커스텀 아이콘 색상도 함께 반영한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-05 15:27:06 +09:00
parent 4c0875446b
commit 928b8446b4
13 changed files with 1458 additions and 117 deletions

View File

@@ -1,5 +1,45 @@
# 의사결정 이력
## 2026-06-05 v1.5.70 — 라이브 멀티라인 Enter는 DOM 조각 삽입 대신 텍스트 값을 갱신한다
콜아웃·인용 본문은 `white-space: pre-wrap`인 plain text contenteditable로 관리한다. Range에 직접 텍스트 노드를 삽입하면 줄바꿈 직후 브라우저 IME 조합 위치가 불안정해져 한글 첫 글자가 자모로 분리될 수 있다. 멀티라인 Enter는 전체 텍스트 값을 기준으로 선택 범위를 `\n`으로 교체하고 커서를 텍스트 오프셋으로 다시 배치한다. 또한 Selection Bridge의 Range 교차 판정을 바로잡고, 콜아웃·인용 전체 선택 삭제는 블록 자체가 아니라 빈 본문 줄을 남기도록 한다.
## 2026-06-05 v1.5.69 — 멀티라인 라이브 편집은 끝 줄바꿈을 보존한다
인용·콜아웃 본문은 하나의 contenteditable 안에서 여러 원본 줄을 대표한다. 이 값 읽기에서 끝 줄바꿈을 잘라내면 마지막 줄에서 Enter를 눌러도 모델에는 새 줄이 남지 않고, 삭제·병합 같은 구조 변경 뒤에는 포커스 중인 오래된 DOM이 blur 때 다시 저장될 수 있다. 멀티라인 plain text 편집은 끝 줄바꿈을 보존해 읽고, 줄 삭제·병합 전에는 stale blur 커밋을 잠시 차단해 부모 모델 갱신이 우선되게 한다.
## 2026-06-05 v1.5.68 — Shift+위/아래 선택은 커서 위치 기준으로 확장한다
라이브 편집은 블록별 contenteditable 구조라 단일 줄 문단 안에서 브라우저 기본 Shift+위/아래가 다음 블록으로 자연스럽게 이어지지 않는다. 블록 끝에서만 확장하는 방식은 textarea의 줄 선택 경험과 달라 실제 글쓰기에서 실패처럼 느껴지므로, 단일 줄 블록에서는 커서 위치와 상관없이 Selection Bridge가 인접 블록의 같은 열로 선택을 확장하도록 바꾼다. 연속 확장 시에는 `sourceLine`이 아니라 Selection의 focus 노드가 속한 편집 요소를 현재 블록으로 사용한다.
## 2026-06-05 v1.5.67 — 라이브 교차 선택 삭제는 DOM이 아니라 마크다운을 갱신한다
교차 블록 선택은 DOM에는 보이지만 각 contenteditable의 키 처리만으로는 삭제가 반영되지 않는다. `lib/markdown-live-selection.js`가 선택 범위를 원본 줄·편집 본문 오프셋으로 변환하고, `ContentMarkdownRenderer``content-replace`로 상위 에디터 본문을 한 번에 갱신한다. Shift+방향키 확장은 줄 범위 탐색과 선택 포커스 경계 판별을 보강하고, Shift 조합 시 블록 이동 단축키와 충돌하지 않게 분리한다.
## 2026-06-05 v1.5.66 — 라이브 선택은 블록 편집 구조를 유지한 채 브리지로 이어준다
라이브 모드를 단일 contenteditable 문서로 바꾸면 Enter·IME·블록 옵션·카드형 블록 편집과 충돌한다. 대신 각 블록 편집기는 유지하고 `ContentMarkdownRenderer`가 Selection API로 Shift 범위 확장과 단계적 전체 선택을 중개한다.
## 2026-06-05 v1.5.65 — IME 확정 Enter의 keyup 경로도 처리한다
일부 브라우저·한글 IME 조합에서는 마지막 글자 확정에 Enter를 쓰면 `keydown`이 contenteditable까지 전달되지 않고 `compositionend``keyup`만 남는다. 이 경우 기존 pending 방식만으로는 줄바꿈 동작을 예약할 수 없어 Enter를 한 번 더 눌러야 했다. 조합 종료 직후 짧은 시간 안에 들어온 Enter `keyup`도 같은 물리 키 입력으로 보고, 현재 Enter 모드에 맞는 블록 동작을 한 번만 실행한다.
## 2026-06-05 v1.5.64 — 텍스트 선택은 블록 이동보다 우선한다
라이브 편집은 블록 단위 contenteditable이 여러 개이므로 문서 전체를 한 번에 드래그 선택할 수는 없다. 다만 각 편집 영역 안에서는 Shift+방향키·전체 선택이 반드시 동작해야 한다. 방향키 블록 이동 단축키가 Shift 조합까지 가로채면 본문 편집이 망가지므로, 선택 제스처일 때는 커스텀 키 처리를 건너뛴다.
## 2026-06-05 v1.5.63 — 라이브 편집 IME Enter 처리는 공통 컴포넌트에서 통일한다
한국어 입력 중 Enter는 브라우저와 IME에 따라 글자 조합 확정 이벤트와 키 입력 이벤트 순서가 다르게 들어온다. 이를 블록별 컴포넌트에서 따로 처리하면 문단·목록·토글 제목·멀티라인 본문 사이의 동작이 다시 달라질 수 있다. 라이브 편집의 모든 텍스트 블록이 `ContentMarkdownEditableInline`을 거치므로, 조합 중 Enter를 공통 pending 동작으로 저장하고 `compositionend` 직후 각 Enter 모드의 실제 동작을 실행하도록 통일한다.
## 2026-05-26 v1.5.62 — Enter 분리 직후 포커스 중 DOM을 modelValue에 맞춘다
문단 Enter 분리는 마크다운을 먼저 갱신하고 Vue가 `modelValue`를 줄인 뒤에도, 포커스 중인 contenteditable은 병합 직전의 긴 문자열을 DOM에 남긴다. 이 상태에서 blur가 나가면 통째 줄이 다시 커밋되어 아래 줄이 복제된 것처럼 보인다. 분리·병합 직후에는 `modelValue`와 DOM을 강제 동기화하고, 구조 변경 직후의 stale blur 커밋은 차단한다.
## 2026-05-26 v1.5.61 — 멀티라인 포커스 시 빈 줄은 편집 영역 전체를 비우지 않는다
콜아웃·코드·토글 본문은 하나의 contenteditable이 `data-source-line`~`data-source-line-end`로 여러 원본 줄을 대표한다. 소스·라이브 전환 후 `focusEditableAtLine`은 대상 원본 줄이 비어 있으면 단일 줄 편집기처럼 DOM을 비우는데, 범위의 첫 줄이 비어 있을 때는 멀티라인 편집기 전체가 지워져 blur 커밋으로 마크다운까지 유실된다. 빈 줄 초기화는 단일 줄 편집기에만 적용하고, 줄 범위가 2줄 이상인 편집기는 해당 원본 줄 위치로 커서만 둔다.
## 2026-06-04 v1.5.54 — 콜아웃 제목 옵션과 기본 아이콘 미사용
콜아웃은 본문 시작 전 시각 신호를 독립적으로 보여주는 편이 여러 줄 본문에서 정렬이 안정적이다. 따라서 라이브·공개 렌더링을 아이콘·제목 헤더와 본문 영역으로 분리하고, 제목은 기존 콜아웃 선언부에 `title` 옵션으로 저장한다. 새 콜아웃은 본문 작성 부담을 줄이기 위해 기본 아이콘 표시를 끄고, 필요할 때 오른쪽 블록 설정 패널에서 켜도록 한다.