velog나 다른 텍스트를 편집할때 에디터를 만들고 싶어 라이브러리를 서치하던 도중
react-quill, @tiptap/react ,@tiptap/starter-kit 이 라이브러리를 사용해 보았다.
처음 react-quill을 사용을 해 보았는데
<ReactQuill
ref={quillRef}
theme="snow"
value={value}
onChange={handleOnChange}
modules={modules}
formats={formats}
placeholder={placeholder}
scrollingContainer={document.body}
/>
이런식으로 사용법이 편리하였다.
formats는
const formats = ["bold", "italic", "underline", "header", "image"];
이런식으로 폰트 굵기 이테릭,언더라인,해더로 formats를 지정해주고
const modules = useMemo(
() => ({
toolbar: false,
keyboard: {
// bindings: {
// paste: {
// key: 'V',
// shortKey: true,
// handler: function() {
// // 기본 붙여넣기 동작 허용
// return true;
// }
// }
// }
},
}),
[]
);
이런식으로 modules를 이용해 option을 지정할 수 있다.
https://www.npmjs.com/package/react-quill
하지만 이 라이브러리가 다른 사이트에서 복사한 글을 붙여넣기 할 때 계속 맨 위로 올라가서
const handleOnChange = useCallback<TextEditorProps["onChange"]>(
(value, delta, source, editor) => {
if (
source === "user" &&
delta.ops?.some(
(op) =>
op.insert && typeof op.insert === "string" && op.insert.length > 1
)
) {
// 붙여넣기 시 현재 스크롤 위치와 커서 위치 저장
const currentScrollPosition = window.scrollY;
const selection = quillRef.current?.getEditor().getSelection();
// 스크롤과 커서 위치 복원
setTimeout(() => {
window.scrollTo({
top: currentScrollPosition,
behavior: "auto",
});
if (selection) {
quillRef.current?.getEditor().setSelection(selection);
}
}, 0);
}
onChange(value, delta, source, editor);
},
[onChange]
);
이 코드를 짜보았고 그래도 똑같은 현상이 일어나서 왜이러지? 라고 생각이 들어 별 방법을 쓰고 chat gpt한테도 물어도 보았는데 해결이 안되어서 다른 라이브러리인 @tiptap/react ,@tiptap/starter-kit 이것을 사용 하였다.
https://tiptap.dev/
사용법은 quill과 같이 간편하게 설정할 수 있었고
<EditorContent editor={editor} />
이렇게 넣어준 후 editor에는
const editor = useEditor({
extensions: [
StarterKit,
Image.configure({
inline: true,
HTMLAttributes: {
class: "editor-image",
},
}),
],
content: value,
onUpdate: ({ editor }) => {
const html = editor?.getHTML();
const textContent = editor?.getText() || "";
if (textContent) {
setIsFocus(true);
}
setCharacterCount(textContent.length);
const mockDelta = {} as DeltaStatic;
const mockSource = "user" as Sources;
const mockEditor = {} as UnprivilegedEditor;
onChange(html, mockDelta, mockSource, editor);
},
editorProps: {
attributes: {
class: "tiptap-editor",
placeholder,
},
},
});
이런식의 훅이 있어서 옵션과 update를 사용하여 이용 할 수 있었고 quill에서 발생한 오류는 발생하지 않아서 다행이었다..