react-md-ast-editor
v0.1.3
Published
Obsidian-style Markdown WYSIWYG editor for React, built on md-ast-parser.
Maintainers
Readme
react-md-ast-editor
Obsidian 스타일의 마크다운 WYSIWYG 에디터. React 용.
▶ 데모 — editor.sim-log.com · 브라우저에서 바로 쳐 볼 수 있다.
커서가 놓인 줄에서는 **굵게** 를 그대로 보여 주고, 다른 줄에서는 별표를 감춰
다듬어진 모습으로 보여 준다. 글을 쓰는 자리에서는 원문이, 읽는 자리에서는 결과가 보인다.
contentEditable 을 쓰지 않는다. 커서와 선택 영역을 직접 그리므로 화면에 무엇이
어떻게 놓일지 전부 통제된다.
설치
npm i react-md-ast-editor md-ast-parsermd-ast-parser 는 peer 이므로 함께 깔아야 한다. React 18 이상이 필요하다.
빠르게 써 보기
import { useState } from 'react'
import { Editor } from 'react-md-ast-editor'
import 'react-md-ast-editor/styles.css'
export default function 글쓰기() {
const [글, set글] = useState('# 제목\n\n**굵게** 와 *기울임*')
return <Editor initialValue={글} onChange={set글} />
}styles.css 를 함께 불러와야 한다. 커서를 감추고 문법 기호를 다루는 규칙이 거기 있다.
높이는 쓰는 쪽에서 정한다. 편집기는 받은 상자를 채운다.
<div style={{ height: 400 }}>
<Editor initialValue={글} onChange={set글} />
</div>Props
| 이름 | 타입 | 설명 |
|---|---|---|
| initialValue | string | 처음 보여 줄 마크다운. 이후 값은 편집기가 들고 있는다 |
| onChange | (value: string) => void | 글이 바뀔 때마다 전체 마크다운을 넘긴다 |
| onUpload | (file: File) => Promise<string> | 그림을 받아 주소를 돌려준다. 넘기지 않으면 그림을 받지 않는다 |
| placeholder | string | 글이 비었을 때 흐리게 비쳐 보일 안내 글 |
| className | string | 바깥 상자에 얹을 이름 |
| surfaceClassName | string | 본문 상자에 얹을 이름. 겉모습을 쓰는 쪽에 맡길 때 쓴다 |
initialValue 는 말 그대로 처음 값이다. 밖에서 값을 바꿔 넣어도 편집기가 따라가지
않는다. 글은 편집기가 들고 있고, 바뀔 때마다 onChange 로 알려준다.
겉모습을 쓰는 쪽에 맡기기
블로그에 얹을 때는 편집기 안의 글이 그 블로그의 글과 같아 보여야 한다.
surfaceClassName 에 이름을 주면 그 이름이 본문 상자에 붙는다.
import 'github-markdown-css/github-markdown.css'
<Editor surfaceClassName="markdown-body" ... />바깥 상자가 아니라 본문 상자에 붙는다. .markdown-body > *:first-child 처럼
바로 아래 자식을 짚는 규칙이 빗나가지 않게 하기 위함이다.
그림 올리기
파일을 받아 주소를 돌려주는 함수만 넘기면, 끌어 놓기와 붙여 넣기를 편집기가 맡는다.
<Editor onUpload={async (file) => {
const 주소 = await 어딘가에올린다(file)
return 주소
}} />올리는 동안에는 자리표시자를 적어 두고, 다 올라가면 그 자리를 실제 주소로 바꾼다. 그 사이 다른 곳을 고쳐도 자리가 어긋나지 않는다.
함수가 실패로 끝나면 적어 둔 자리를 걷어낸다. 크기 제한처럼 받지 않을 까닭이 있으면 던지면 된다.
올리기를 미루고 싶다면 브라우저가 들고 있는 자리를 돌려주어도 된다. 글을 저장할 때 한꺼번에 올리는 식이다.
<Editor onUpload={async (file) => URL.createObjectURL(file)} />다루는 문법
| | | |---|---| | 블럭 | 제목, 문단, 목록(순서·무순서, 중첩), 인용문, 코드블럭, 구분선 | | 인라인 | 굵게, 기울임, 인라인 코드, 링크, 그림 | | 겹침 | 인용문 안의 목록처럼 한 줄이 여러 블럭을 지나는 경우 |
코드블럭은 shiki 로 문법 강조를 입힌다. 파서가 데리고 온다.
표는 아직 다루지 않는다.
되는 것
- 한글 조합. 조합 중인 글자를 고르는 창이 커서 자리에 뜬다
- 되돌리기와 다시 실행. 이어 친 글자는 한 번에 되돌아간다
- 마우스로 커서를 놓고 범위를 끌기, 전체 선택
- 위아래 이동. 긴 줄이 화면에서 접혀도 접힌 줄을 따라 움직이고, 짧은 줄을 지나도 원래 열로 돌아온다
- 줄이 수천이어도 보이는 만큼만 그린다. 제목과 코드블럭처럼 높이가 제각각이어도 된다
개발
npm install
npm test # 리듀서와 위치 매핑
npm run typecheck
npm run build
npm run demo # 데모jsdom 에는 레이아웃이 없어 화면 좌표는 테스트로 검증할 수 없다. 커서와 선택 영역이 제자리에 놓이는지는 데모를 띄워 확인한다.
설계
어떻게 만들었고 왜 그렇게 했는지는 docs/DESIGN.md 에 있다.
라이선스
MIT
