simple-tiptap-vue3-editor
v1.0.2
Published
A simple Tiptap editor component for Vue 3 that is added some table features
Maintainers
Readme
tiptap-simple-editor
TipTap 에디터를 Vue 개발자들이 편하게 가져다 사용할 수 있도록 스타일링한 라이브러리입니다.
📑 목차
- ✨ 주요 기능
- 🚀 빠른 시작
- 설치
- 기본적으로 프로젝트에 설치가 되어 있어야 하는 라이브러리
- 사용 방법
- 추가되어 있는 기능
- 이미지 업로드 방법
- Props
- 이벤트
- 📚 추가 사용 예시
- 🎨 스타일 커스터마이징
- ⚠️ 주의사항
- 🔧 문제 해결 (Troubleshooting)
- 💻 로컬 개발
- 🌐 브라우저 지원
- 📄 라이선스
✨ 주요 기능
- 🎨 즉시 사용 가능한 스타일링: 별도 스타일 작업 없이 바로 사용
- 📝 풍부한 텍스트 편집: Bold, Italic, Heading, 정렬, 하이라이트 등
- 📋 강력한 테이블 기능: 우클릭 컨텍스트 메뉴로 쉬운 테이블 편집
- 🖼️ 이미지 업로드: 커스텀 업로드 핸들러 지원
- ✅ Task List: 체크박스 기능이 포함된 할 일 목록
- 🔗 링크 삽입: URL 링크 추가 기능
- 🎯 Vue 3 최적화: Composition API 및 TypeScript 지원
🚀 빠른 시작
# 1. 라이브러리 설치
npm install simple-tiptap-editor
# 2. 필수 의존성 설치 (아직 설치하지 않은 경우)
npm install vue@^3.5.0 @tiptap/vue-3@^3.10.0 @tiptap/pm@^3.10.0 @tiptap/starter-kit@^3.10.0<!-- 3. 컴포넌트에서 사용 -->
<template>
<TiptapEditor v-model="content" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { TiptapEditor } from 'simple-tiptap-editor'
import 'simple-tiptap-editor/style.css'
const content = ref('<p>내용을 입력하세요.</p>')
</script>설치
npm install simple-tiptap-editor기본적으로 프로젝트에 설치가 되어 있어야 하는 라이브러리
이 라이브러리는 다음 패키지들을 peer dependencies로 요구합니다:
npm install vue@^3.5.0 @tiptap/vue-3@^3.10.0 @tiptap/pm@^3.10.0 @tiptap/starter-kit@^3.10.0사용 방법
<template>
<div>
<TiptapEditor v-model="content" :on-image-upload="handleImageUpload" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { TiptapEditor } from 'simple-tiptap-editor'
import 'simple-tiptap-editor/style.css'
const content = ref('<p>여기에 초기 내용을 입력하세요.</p>')
// 이미지 업로드 핸들러 (선택사항)
const handleImageUpload = async (file: File): Promise<string> => {
// 파일을 서버에 업로드하고 URL을 반환
const formData = new FormData()
formData.append('image', file)
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
})
const data = await response.json()
return data.url
}
</script>추가되어 있는 기능
기본 텍스트 편집
- 텍스트 서식: Bold, Italic, Strike
- 제목 레벨: Heading 1~6, Paragraph
- 텍스트 정렬: 좌측, 가운데, 우측 정렬
- 하이라이트: 텍스트 형광펜 효과
- 인용구: Block Quote
- 구분선: Horizontal Rule
리스트 기능
- Bullet List (순서 없는 목록)
- Ordered List (순서 있는 목록)
- Task List (체크박스 목록)
테이블 기능
- 테이블 삽입 (최대 10x10 그리드)
- 우클릭 컨텍스트 메뉴를 통한 테이블 편집:
- 왼쪽/오른쪽에 열 추가
- 열 삭제
- 위/아래에 행 추가
- 행 삭제
- 셀 병합
- 셀 분리
- 셀 수직 정렬 (상단/가운데/하단)
- 테이블 삭제
이미지 및 링크
- 이미지 업로드 및 삽입
- 링크 삽입
이미지 업로드 방법
이미지 업로드는 두 가지 방식으로 처리할 수 있습니다:
1. 커스텀 업로드 핸들러 사용 (권장)
onImageUpload prop을 사용하여 자체 서버에 이미지를 업로드하는 함수를 전달할 수 있습니다:
<TiptapEditor v-model="content" :on-image-upload="handleImageUpload" />const handleImageUpload = async (file: File): Promise<string> => {
// 서버로 파일 업로드
const formData = new FormData()
formData.append('image', file)
const response = await fetch('https://your-api.com/upload', {
method: 'POST',
body: formData,
})
const { url } = await response.json()
return url // 업로드된 이미지 URL 반환
}2. 기본 동작 (Blob URL)
onImageUpload prop을 제공하지 않으면, 이미지는 브라우저의 Blob URL로 로컬에서만 표시됩니다. 이 방식은 개발 중이거나 임시로 사용하기에 적합합니다.
<TiptapEditor v-model="content" />Props
| Prop | 타입 | 필수 | 설명 |
| --------------- | --------------------------------- | ---- | ----------------------- |
| modelValue | string | ✅ | 에디터의 HTML 콘텐츠 |
| onImageUpload | (file: File) => Promise<string> | ❌ | 이미지 업로드 처리 함수 |
이벤트
| 이벤트 | 페이로드 | 설명 |
| ------------------- | -------- | ------------------------------ |
| update:modelValue | string | 에디터 콘텐츠가 변경될 때 발생 |
🎨 스타일 커스터마이징
에디터의 스타일을 커스터마이징하려면 CSS 변수를 오버라이드하거나 직접 스타일을 작성할 수 있습니다:
/* 에디터 컨테이너 스타일 변경 */
.tiptap-editor-container {
border: 2px solid #e0e0e0;
border-radius: 8px;
}
/* 에디터 툴바 버튼 스타일 */
.editor-feature-btn {
padding: 8px;
border-radius: 4px;
}
.editor-feature-btn:hover {
background-color: #f5f5f5;
}
/* 활성화된 버튼 스타일 */
.editor-feature-btn.is-active {
background-color: #e3f2fd;
}
/* 에디터 콘텐츠 영역 */
.ProseMirror {
min-height: 300px;
padding: 16px;
}⚠️ 주의사항
1. CSS 파일 Import 필수
반드시 CSS 파일을 import해야 에디터가 정상적으로 표시됩니다:
import 'simple-tiptap-editor/style.css'2. v-model 사용
양방향 바인딩을 위해 v-model을 사용해야 합니다:
<!-- ✅ 올바른 사용법 -->
<TiptapEditor v-model="content" />
<!-- ❌ 잘못된 사용법 -->
<TiptapEditor :modelValue="content" @update:modelValue="content = $event" />3. 이미지 업로드 핸들러
프로덕션 환경에서는 반드시 onImageUpload prop을 사용하여 서버에 이미지를 업로드하세요. Blob URL은 페이지 새로고침 시 사라집니다.
🔧 문제 해결 (Troubleshooting)
CSS가 적용되지 않아요
라이브러리의 CSS 파일을 import했는지 확인하세요:
import 'simple-tiptap-editor/style.css'Vite를 사용하는 경우 vite.config.ts에서 CSS 처리가 활성화되어 있는지 확인하세요.
이미지가 업로드되지 않아요
onImageUploadprop에 올바른 함수를 전달했는지 확인하세요- 함수가 반드시 이미지 URL을
Promise<string>형태로 반환해야 합니다 - 서버의 업로드 엔드포인트가 정상 작동하는지 확인하세요
- 브라우저 콘솔에서 오류 메시지를 확인하세요
const handleImageUpload = async (file: File): Promise<string> => {
try {
// 업로드 로직
const url = await uploadToServer(file)
return url
} catch (error) {
console.error('이미지 업로드 실패:', error)
throw error // 에러를 던져서 사용자에게 알림
}
}테이블 우클릭 메뉴가 나타나지 않아요
테이블 셀 안에서 우클릭했는지 확인하세요. 테이블 영역이 아닌 곳에서는 컨텍스트 메뉴가 나타나지 않습니다.
내용이 업데이트되지 않아요
v-model을 사용하고 있는지 확인하세요:
<!-- ❌ 잘못된 사용법 -->
<TiptapEditor :model-value="content" />
<!-- ✅ 올바른 사용법 -->
<TiptapEditor v-model="content" />TypeScript 타입 오류가 발생해요
필요한 경우 타입을 명시적으로 import하세요:
import type { TiptapEditor } from 'simple-tiptap-editor'성능 문제가 있어요
매우 긴 문서를 편집할 때 성능 문제가 발생할 수 있습니다. 이 경우:
- 문서를 여러 섹션으로 나누기
- 필요한 경우 debounce를 사용하여 저장 빈도 줄이기
import { ref, watch } from 'vue'
import { debounce } from 'lodash-es'
const content = ref('')
// 500ms debounce를 적용하여 저장
const debouncedSave = debounce((value: string) => {
// 서버에 저장
saveToServer(value)
}, 500)
watch(content, (newValue) => {
debouncedSave(newValue)
})💻 로컬 개발
이 라이브러리를 로컬에서 개발하고 싶다면:
# 저장소 클론
git clone https://github.com/your-repo/tiptap-simple-editor.git
cd tiptap-simple-editor
# 의존성 설치
npm install
# 개발 서버 실행
npm run dev
# 라이브러리 빌드
npm run build:lib🌐 브라우저 지원
- Chrome (최신 버전)
- Firefox (최신 버전)
- Safari (최신 버전)
- Edge (최신 버전)
📄 라이선스
MIT
