Step 3-A — 명령어 입력 기반 (history · InputRules · keymap)
상태: ✅ 완료 (2026-04-14) 목표: 슬래시 명령 메뉴(3-B) 를 구현하기 전에, 파워유저가 타이핑과 단축키만으로 모든 편집을 수행할 수 있는 기반을 마련한다.
목차
설치된 의존성
prosemirror-history ^1.4.x — undo/redo 스택 관리
prosemirror-inputrules ^1.4.x — 타이핑 중 자동 변환 규칙 엔진
prosemirror-schema-list ^1.5.x — splitListItem / liftListItem / sinkListItem추가된 파일
src/plugins/input-rules.ts (신규)
prosemirror-inputrules 의 헬퍼(wrappingInputRule, textblockTypeInputRule, smartQuotes, emDash, ellipsis) 를 조합하여 Markdown 스타일 자동 변환 규칙을 정의. 스키마 존재 여부를 체크하여 조건부로 규칙을 추가한다.
적용 규칙:
| 패턴 | 변환 결과 |
|---|---|
> (공백 포함) | blockquote 래핑 |
- / * / + | bullet list 래핑 |
숫자. | ordered list 래핑 (시작 번호 인식) |
``` | code block 변환 |
# ~ ###### | heading 1~6 변환 (# 개수로 레벨 결정) |
"..." / '...' | 스마트 인용 부호 |
-- | em-dash (—) |
... | ellipsis (…) |
src/plugins/keymap.ts (신규)
prosemirror-keymap + prosemirror-commands + prosemirror-history + prosemirror-schema-list 를 조합한 확장 키맵.
| 키 | 동작 |
|---|---|
Mod-z | undo |
Mod-y, Shift-Mod-z | redo |
Mod-b | toggle strong |
Mod-i | toggle em |
Mod-` | toggle inline code |
Enter | (리스트 안) splitListItem |
Tab | (리스트 안) sinkListItem — 중첩 들여쓰기 |
Shift-Tab | (리스트 안) liftListItem — 내어쓰기 |
Mod= macOSCmd, Windows/LinuxCtrl
src/index.ts (수정)
플러그인 배열 확장. 순서 중요:
ts
plugins: [
history(), // 1. 히스토리 트래킹 (가장 먼저)
buildInputRules(schema), // 2. 타이핑 자동 변환
buildKeymap(schema), // 3. 확장 키맵 (마크, 리스트, undo)
keymap(baseKeymap), // 4. 기본 키맵 (fallback)
]ProseMirror는 플러그인을 앞에서부터 순차 처리 하며, 먼저 handleKeyDown 을 처리한 플러그인이 이기면 뒤 플러그인은 호출되지 않는다. 따라서:
- 리스트 안에서
Enter→buildKeymap이splitListItem으로 처리 - 리스트 밖에서
Enter→baseKeymap이createParagraphNear등으로 처리
index.html (수정)
노란색 힌트 박스 추가 — 사용자가 열자마자 주요 입력 방식을 안내.
플러그인 구성
┌──────────────────────────────────────────┐
│ NewtilEditor Web Component │
│ │
│ EditorView │
│ ├─ history() ← undo/redo │
│ ├─ buildInputRules() ← 타이핑 변환 │
│ ├─ buildKeymap() ← 확장 키 │
│ └─ keymap(baseKeymap) ← 기본 키 │
│ │
│ Schema: prosemirror-markdown 기본 │
└──────────────────────────────────────────┘제공되는 입력 수단
Step 3-A 시점에서 슬래시 메뉴 없이도 가능해진 것들:
블록 만들기 (Markdown 타이핑)
# 제목→ H1 제목## 제목→ H2 제목### 제목→ H3 제목- 항목→ 불릿 리스트1. 항목→ 번호 리스트> 인용→ blockquote```+ Enter → 코드 블럭
인라인 서식 (단축키)
Mod-B→ 굵게 (선택 영역 토글)Mod-I→ 기울임Mod-`→ 인라인 코드
구조 조작
Mod-Z→ 되돌리기Mod-Shift-Z/Mod-Y→ 다시 실행- 리스트 안에서
Tab→ 중첩 들여쓰기 - 리스트 안에서
Shift-Tab→ 내어쓰기 - 리스트 안에서
Enter→ 새 리스트 항목 - 리스트 안에서
Enter(빈 항목) → 리스트 탈출 (baseKeymap 연계)
검증 결과
| 명령 | 결과 |
|---|---|
npm run typecheck | ✅ 오류 0건 |
npm run build | ✅ ESM 7.70KB + CJS 8.33KB + DTS |
npm run dev | ✅ HMR 정상, 3개 신규 의존성 자동 최적화 |
브라우저 수동 확인 (http://localhost:5174):
#+ 스페이스 → heading 생성-+ 스페이스 → 불릿 리스트 생성- 리스트 안에서 Enter → 새 항목 생성
Cmd+B+ 타이핑 → 굵게 입력 모드- 편집 후
Cmd+Z→ 이전 상태로 되돌리기 - 리스트 항목에서
Tab→ 들여쓰기 - 하단 Markdown 패널에 올바른
#,-,**형태로 직렬화 확인
알려진 제한 / 3-B 에서 해결할 것
| 제한 | 해결 예정 |
|---|---|
| 단축키·Markdown 문법을 몰라도 명령 접근할 방법 없음 | Step 3-B (슬래시 메뉴) |
| 링크 삽입 UI 없음 | Step 3-B (Link 명령 + URL 모달) |
| 이미지 삽입 UI 없음 | Step 3-B (Image 명령 + URL 모달) |
| H4~H6 는 Markdown 타이핑으로만 가능 | Step 3-B (Heading 4-6 드롭다운) |
| 선택 영역 기반 툴바 없음 | Step 4 |
| 현재 mark 활성화 상태 시각 표시 없음 | Step 4 (floating toolbar) |
placeholder, readonly 속성 없음 | Step 4 |
설계 변경 이력
2026-04-14 — Step 3 재정의
원래 Step 3 는 "툴바 / 단축키 / InputRules" 였으나, 슬래시 명령 메뉴가 주 UX 여야 한다는 사용자 결정에 따라 재구성:
- Step 3: 명령어 입력 시스템 (3-A 기반 + 3-B 슬래시 메뉴)
- Step 4 (신규): 툴바 + 속성 + 이벤트
- Step 5: CSS 격리 + 테마 (기존 Step 4)
- Step 6: React/Vue 래퍼 (기존 Step 5)
- Step 7: npm 배포 (기존 Step 6)