# @mvp-factory/holy-editor

성경 구절 통합 및 PWA 지원을 갖춘 리치 텍스트 에디터

## ✨ 주요 기능

- 📖 **성경 구절 슬래시 명령어**: `/갈2:20`, `/요3:16-17` 형식으로 성경 구절 자동 삽입
- ✏️ **리치 텍스트 편집**: Bold, Underline, Heading, Quote, Color 포맷팅
- 📱 **PWA 최적화**: 모바일 키보드 추적 및 UI 조정
- 🎨 **컬러 피커**: 8색 팔레트로 텍스트 색상 변경
- 🔔 **알림 시스템**: 사용자 피드백을 위한 토스트 메시지
- 💾 **자동 저장**: localStorage를 통한 주기적 내용 저장 및 복원
- 🚀 **TypeScript 지원**: 완전한 타입 정의
- 📦 **모듈화 설계**: 개별 컴포넌트 독립적 사용 가능

## 🚀 빠른 시작

### 설치

```bash
npm install @mvp-factory/holy-editor
```

### 기본 사용법

```html
<!-- HTML -->
<div id="myEditor" contenteditable="true"></div>
```

```typescript
// TypeScript/JavaScript
import { HolyEditor } from '@mvp-factory/holy-editor';

const editor = new HolyEditor('myEditor', {
  enableBibleVerses: true,
  enableTextFormatting: true,
  enablePWAKeyboard: true,
  enableAutoSave: true,
  apiEndpoint: '/api/bible_verse_full.php'
});

editor.initialize();
```

### CSS 스타일 (기본)

```css
.holy-editor {
  min-height: 200px;
  padding: 16px;
  border: 1px solid #ddd;
  border-radius: 8px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  line-height: 1.6;
}

.bible-verse {
  background: #f8f9fa;
  border-left: 4px solid #007bff;
  padding: 12px 16px;
  margin: 16px 0;
  border-radius: 4px;
}

.verse-reference {
  display: block;
  margin-top: 8px;
  font-size: 0.9em;
  color: #666;
  font-style: normal;
}
```

## 📖 성경 구절 기능

### 슬래시 명령어

에디터에서 다음 형식으로 입력하면 자동으로 성경 구절이 삽입됩니다:

```
/갈2:20     → 갈라디아서 2장 20절
/요3:16     → 요한복음 3장 16절
/시23:1-3   → 시편 23편 1-3절 (범위 구절)
/창1:1      → 창세기 1장 1절
```

### 지원하는 성경책 (66권)

**구약 39권**:
창, 출, 레, 민, 신, 수, 삿, 룻, 삼상, 삼하, 왕상, 왕하, 대상, 대하, 스, 느, 에, 욥, 시, 잠, 전, 아, 사, 렘, 애, 겔, 단, 호, 욜, 암, 옵, 욘, 미, 나, 합, 습, 학, 슥, 말

**신약 27권**:
마, 막, 눅, 요, 행, 롬, 고전, 고후, 갈, 엡, 빌, 골, 살전, 살후, 딤전, 딤후, 딛, 몬, 히, 약, 벧전, 벧후, 요일, 요이, 요삼, 유, 계

### 프로그래밍 방식으로 구절 삽입

```typescript
// 특정 구절 삽입
await editor.insertVerse('갈2:20');

// 범위 구절 삽입
await editor.insertVerse('시23:1-6');

// 성공/실패 확인
const success = await editor.insertVerse('요3:16');
if (success) {
  console.log('구절이 성공적으로 삽입되었습니다');
}
```

## ✏️ 텍스트 포맷팅

### 키보드 단축키

- `Ctrl+B` / `Cmd+B`: **굵게**
- `Ctrl+U` / `Cmd+U`: <u>밑줄</u>
- `Ctrl+H` / `Cmd+H`: # 제목
- `Ctrl+Q` / `Cmd+Q`: > 인용구

### 프로그래밍 방식 포맷팅

```typescript
// 포맷 토글
editor.toggleFormat('bold');
editor.toggleFormat('underline');
editor.toggleFormat('heading1');
editor.toggleFormat('quote');

// 텍스트 색상 적용
editor.applyTextColor('#ff0000');

// 컬러 피커 표시
editor.showColorPicker();

// 현재 포맷 상태 확인
const formatState = editor.getFormatState();
console.log(formatState?.bold); // true/false
```


## 💾 자동 저장 기능

내용을 주기적으로 localStorage에 자동 저장하고, 에디터 재시작 시 복원할 수 있습니다.

### 기본 설정

```typescript
const editor = new HolyEditor('myEditor', {
  enableAutoSave: true,       // 자동 저장 활성화 (기본: true)
  autoSaveInterval: 30000,    // 저장 주기 (기본: 30초)
  autoSaveKey: 'my-custom-key' // 커스텀 저장 키 (선택사항)
});
```

### 수동 제어

```typescript
// 즉시 저장
const saved = editor.saveContent();
if (saved) {
  console.log('내용이 저장되었습니다');
}

// 저장된 내용 확인
if (editor.hasSavedContent()) {
  const info = editor.getAutoSaveInfo();
  console.log('마지막 저장:', new Date(info.lastSave));
}

// 저장된 내용 삭제
editor.clearSavedContent();

// 자동 저장 토글
editor.toggleAutoSave(false); // 비활성화
editor.toggleAutoSave(true);  // 활성화

// 저장 주기 변경 (60초로)
editor.updateAutoSaveInterval(60000);
```

### 복원 동작

에디터 초기화 시 저장된 내용이 있으면 사용자에게 복원 여부를 확인합니다:

```text
"이전에 작성하던 내용이 있습니다 (5분 전).
복원하시겠습니까?"

[확인] [취소]
```

### 모든 에디터의 저장 내용 관리

```typescript
import { AutoSaveManager } from '@mvp-factory/holy-editor';

// 저장된 모든 에디터 ID 확인
const savedEditors = AutoSaveManager.getAllSavedEditors();
console.log('저장된 에디터:', savedEditors);

// 모든 저장 내용 삭제
const cleared = AutoSaveManager.clearAll();
console.log(`${cleared}개의 에디터 저장 내용을 삭제했습니다`);
```
## 📱 PWA 지원

모바일 환경에서 가상 키보드가 나타날 때 자동으로 UI를 조정합니다.

```typescript
const editor = new HolyEditor('myEditor', {
  enablePWAKeyboard: true,
  keyboardSettings: {
    threshold: 10,      // 감지 임계값 (px)
    keyboardMin: 150,   // 최소 키보드 높이 (px)
    debounceTime: 0     // 디바운스 시간 (ms)
  }
});
```

### PWA 환경 감지

```typescript
import { PWAKeyboardTracker } from '@mvp-factory/holy-editor';

const tracker = new PWAKeyboardTracker();
const env = tracker.getEnvironmentInfo();

console.log('PWA 환경:', env.isPWA);
console.log('iOS 기기:', env.isIOS);
console.log('Android 기기:', env.isAndroid);
console.log('Visual Viewport API 지원:', env.hasVisualViewport);
```

## ⚙️ 설정 옵션

```typescript
interface EditorConfig {
  // 기능 활성화/비활성화
  enableBibleVerses?: boolean;      // 성경 구절 기능 (기본: true)
  enableTextFormatting?: boolean;   // 텍스트 포맷팅 (기본: true)
  enablePWAKeyboard?: boolean;      // PWA 키보드 추적 (기본: true)
  enableColorPicker?: boolean;      // 컬러 피커 (기본: true)
  enableAutoSave?: boolean;         // 자동 저장 (기본: true)
  
  // API 설정
  apiEndpoint?: string;             // 성경 API 엔드포인트
  debounceMs?: number;              // 입력 디바운스 시간 (기본: 300ms)
  
  // 자동 저장 설정
  autoSaveInterval?: number;        // 자동 저장 주기 (기본: 30000ms)
  autoSaveKey?: string;             // localStorage 키 (기본: 'holy-editor-autosave-{editorId}')
  
  // PWA 키보드 설정
  keyboardSettings?: {
    threshold?: number;             // 감지 임계값 (기본: 10px)
    keyboardMin?: number;           // 최소 키보드 높이 (기본: 150px)
    debounceTime?: number;          // 디바운스 시간 (기본: 0ms)
  };
}
```

## 🎨 스타일링 가이드

### CSS 클래스

에디터에서 사용하는 주요 CSS 클래스들:

```css
/* 에디터 본체 */
.holy-editor { /* 기본 에디터 스타일 */ }
.holy-editor-focused { /* 포커스 상태 */ }

/* 성경 구절 */
.bible-verse { /* 단일 구절 */ }
.bible-verse-range { /* 범위 구절 */ }
.verse-text { /* 구절 텍스트 */ }
.verse-reference { /* 구절 참조 */ }

/* 포맷팅 */
.inline-quote { /* 인라인 인용구 */ }

/* 알림 */
.holy-toast { /* 토스트 메시지 */ }
.holy-toast-success { /* 성공 메시지 */ }
.holy-toast-error { /* 오류 메시지 */ }

/* 컬러 피커 */
.holy-color-picker { /* 컬러 피커 다이얼로그 */ }

/* PWA */
.keyboard-active { /* 키보드 활성화 상태 */ }
.keyboard-tracking { /* 키보드 추적 중 */ }
```

### 테마 커스터마이징

```css
/* 다크 테마 예시 */
.holy-editor.dark-theme {
  background-color: #1a1a1a;
  color: #ffffff;
  border-color: #444;
}

.dark-theme .bible-verse {
  background-color: #2d2d2d;
  border-left-color: #0d7377;
}

.dark-theme .verse-reference {
  color: #aaa;
}
```

## 🔧 API 참조

### HolyEditor 클래스

#### 생성자

```typescript
new HolyEditor(editorId: string, config?: Partial<EditorConfig>)
```

#### 메서드

```typescript
// 초기화 및 해제
initialize(): void                              // 에디터 초기화
destroy(): void                                 // 에디터 해제 및 정리

// 내용 관리
getContent(): string                            // HTML 내용 가져오기
setContent(html: string): void                  // HTML 내용 설정
getTextContent(): string                        // 텍스트만 가져오기
clear(): void                                   // 내용 지우기

// 포커스 관리
focus(): void                                   // 에디터 포커스
isFocused(): boolean                            // 포커스 상태 확인

// 포맷팅
toggleFormat(action: FormatAction): void        // 포맷 토글
applyTextColor(color: string): void             // 색상 적용
showColorPicker(): void                         // 컬러 피커 표시
getFormatState(): FormatState | null           // 현재 포맷 상태

// 성경 구절
insertVerse(ref: string): Promise<boolean>      // 구절 삽입

// 자동 저장
saveContent(): boolean                           // 즉시 저장
clearSavedContent(): boolean                     // 저장 내용 삭제
hasSavedContent(): boolean                       // 저장 내용 존재 여부
getAutoSaveInfo(): object                        // 자동 저장 정보
updateAutoSaveInterval(ms: number): void         // 저장 주기 변경
toggleAutoSave(enable?: boolean): void           // 자동 저장 토글
```

### 개별 컴포넌트 사용

```typescript
import { 
  BibleVerseEngine, 
  TextFormatter, 
  PWAKeyboardTracker,
  ToastManager, 
  ColorPicker,
  AutoSaveManager 
} from '@mvp-factory/holy-editor';

// 성경 구절 엔진만 사용
const bibleEngine = BibleVerseEngine.getInstance();
const isValid = bibleEngine.isValidBibleRef('갈2:20');
const verseData = await bibleEngine.loadVerse('갈2:20');

// 토스트 메시지만 사용
const toast = ToastManager.getInstance();
toast.success('성공적으로 저장되었습니다');
toast.error('오류가 발생했습니다');

// 컬러 피커만 사용
const colorPicker = ColorPicker.getInstance();
colorPicker.show((color) => {
  console.log('Selected color:', color);
});

// 자동 저장 관리만 사용
const autoSave = new AutoSaveManager('myEditor', {
  interval: 60000,  // 1분마다 저장
  onSave: (data) => console.log('저장됨:', data),
  onError: (error) => console.error('저장 실패:', error)
});

// 에디터 내용 가져오기 함수
const getContent = () => document.getElementById('myEditor').innerHTML;

// 자동 저장 시작
autoSave.start(getContent);

// 나중에 중지
autoSave.stop();
```

## 🚀 고급 사용법

### 커스텀 성경 API 연동

```typescript
const editor = new HolyEditor('myEditor', {
  apiEndpoint: 'https://api.mybible.com/verse',
  debounceMs: 500
});

// API 응답 형식
interface BibleApiResponse {
  success: boolean;
  verses: Array<{
    book: string;
    chapter: number;
    verse: number;
    text: string;
  }>;
}
```

### 이벤트 리스너

```typescript
const editorElement = document.getElementById('myEditor');

// 포맷 상태 변경 이벤트
editorElement?.addEventListener('holyeditor:formatstatechange', (event) => {
  const formatState = event.detail;
  updateToolbarButtons(formatState);
});

// 커스텀 이벤트 리스너 함수
function updateToolbarButtons(formatState: FormatState) {
  document.getElementById('boldBtn')?.classList.toggle('active', formatState.bold);
  document.getElementById('underlineBtn')?.classList.toggle('active', formatState.underline);
  // ...
}
```

### 툴바 통합 예시

```html
<div class="editor-toolbar">
  <button id="boldBtn" onclick="editor.toggleFormat('bold')">굵게</button>
  <button id="underlineBtn" onclick="editor.toggleFormat('underline')">밑줄</button>
  <button id="headingBtn" onclick="editor.toggleFormat('heading1')">제목</button>
  <button id="quoteBtn" onclick="editor.toggleFormat('quote')">인용</button>
  <button id="colorBtn" onclick="editor.showColorPicker()">색상</button>
</div>
<div id="myEditor" contenteditable="true"></div>
```

```css
.editor-toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
  padding: 8px;
  border-bottom: 1px solid #ddd;
}

.editor-toolbar button {
  padding: 8px 12px;
  border: 1px solid #ddd;
  background: white;
  border-radius: 4px;
  cursor: pointer;
}

.editor-toolbar button.active {
  background: #007bff;
  color: white;
}
```

## 🛠️ 개발 환경 설정

### 타입스크립트 프로젝트에서 사용

```json
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["DOM", "DOM.Iterable", "ES2020"],
    "module": "ESNext",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
```

### 번들러 설정 (Webpack/Vite)

```javascript
// vite.config.js
export default {
  optimizeDeps: {
    include: ['@mvp-factory/holy-editor']
  }
}
```

## 🐛 문제 해결

### 일반적인 문제들

**1. 성경 구절이 로드되지 않는 경우**
```typescript
// API 엔드포인트 확인
const editor = new HolyEditor('myEditor', {
  apiEndpoint: '/your-api-endpoint.php'  // 올바른 엔드포인트 설정
});

// 네트워크 탭에서 API 응답 확인
// CORS 설정 확인
```

**2. PWA에서 키보드 추적이 작동하지 않는 경우**
```typescript
// Visual Viewport API 지원 확인
const tracker = new PWAKeyboardTracker();
console.log('Visual Viewport 지원:', tracker.hasVisualViewport());

// 매뉴얼 업데이트
tracker.forceUpdate();
```

**3. 스타일이 적용되지 않는 경우**
```css
/* CSS 우선순위 확인 */
.holy-editor {
  /* !important 사용 시 주의 */
}

/* 또는 더 구체적인 선택자 사용 */
#myEditor.holy-editor {
  /* 스타일 */
}
```

**4. 자동 저장이 작동하지 않는 경우**
```typescript
// localStorage 사용 가능 여부 확인
try {
  localStorage.setItem('test', 'test');
  localStorage.removeItem('test');
  console.log('localStorage 사용 가능');
} catch (e) {
  console.error('localStorage 사용 불가:', e);
}

// 저장 용량 확인
const info = editor.getAutoSaveInfo();
if (!info.isRunning) {
  console.log('자동 저장이 비활성화되어 있습니다');
}
```

## 📄 라이센스

MIT License

## 🤝 기여하기

1. 이 저장소를 Fork 하세요
2. 새로운 기능 브랜치를 생성하세요 (`git checkout -b feature/AmazingFeature`)
3. 변경 사항을 커밋하세요 (`git commit -m 'Add some AmazingFeature'`)
4. 브랜치에 Push 하세요 (`git push origin feature/AmazingFeature`)
5. Pull Request를 열어주세요

## 📞 지원

- GitHub Issues: [이슈 생성](https://github.com/mvp-factory/holy-editor/issues)
- 문서: [전체 문서 보기](https://docs.mvp-factory.com/holy-editor)

---

**@mvp-factory/holy-editor** - 성경 중심 리치 텍스트 에디터 🙏✨