@junbyeol/tiptap-editor 1.0.12 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,10 +39,11 @@ export default function App() {
39
39
  | `minHeight` | `string` | 콘텐츠 영역 최소 높이 (기본값: `200px`) |
40
40
  | `maxHeight` | `string` | 콘텐츠 영역 최대 높이. 초과 시 내부 스크롤 (기본값: 없음) |
41
41
  | `uploadFile` | `(file: File) => Promise<string>` | 파일을 업로드하고 URL을 반환. 미제공 시 base64로 브라우저 메모리에 저장 |
42
- | `onFileInsert` | `(file: File) => void` | 파일이 에디터에 삽입될 호출 |
43
- | `onFileError` | `(error: Error) => void` | 파일 처리 오류 시 호출 |
42
+ | `onUploadStart` | `(file: File) => void` | 파일 업로드 시작 호출 |
43
+ | `onUploadSuccess` | `(file: File) => void` | 파일 업로드 성공 시 호출 |
44
+ | `onUploadError` | `(error: Error) => void` | 파일 업로드 오류 시 호출 |
44
45
  | `allowNonImageFile` | `boolean` | 이미지 외 파일(PDF 등) 허용 여부 (기본값: `false`) |
45
- | `FileAttachmentComponent` | `ComponentType<FileAttachmentAttributes>` | 비이미지 파일을 렌더링할 컴포넌트 |
46
+ | `FileAttachmentComponent` | `ComponentType<FileAttachmentAttributes>` | 비이미지 파일을 렌더링할 컴포넌트. `allowNonImageFile`이 `true`일 때 유효 |
46
47
 
47
48
  ### 파일 업로드 예시
48
49
 
@@ -62,23 +63,139 @@ export default function App() {
62
63
  return (
63
64
  <TiptapEditor
64
65
  uploadFile={uploadFile}
65
- onFileInsert={(file) => console.log("삽입됨:", file.name)}
66
- onFileError={(error) => console.error(error)}
66
+ onUploadStart={(file) => console.log("업로드 시작:", file.name)}
67
+ onUploadSuccess={(file) => console.log("업로드 완료:", file.name)}
68
+ onUploadError={(error) => console.error(error)}
67
69
  allowNonImageFile
68
70
  />
69
71
  );
70
72
  }
71
73
  ```
72
74
 
75
+ ## 콘텐츠 렌더링 (읽기 전용)
76
+
77
+ 저장된 HTML을 읽기 전용으로 표시할 때는 `TiptapContent`를 사용합니다. 에디터 없이 콘텐츠 스타일만 적용된 뷰어 역할을 합니다.
78
+
79
+ ```tsx
80
+ import { TiptapContent } from "@junbyeol/tiptap-editor";
81
+ import "@junbyeol/tiptap-editor/style.css";
82
+
83
+ export default function PostPage({ post }) {
84
+ return <TiptapContent html={post.content} />;
85
+ }
86
+ ```
87
+
88
+ ### Props
89
+
90
+ | Prop | 타입 | 설명 |
91
+ | ----------- | -------- | --------------------------------------------- |
92
+ | `html` | `string` | 렌더링할 HTML 문자열 (필수) |
93
+ | `className` | `string` | 루트 `div`에 추가할 CSS 클래스 (선택) |
94
+
95
+ ## 폰트 적용
96
+
97
+ 에디터에서 선택할 수 있는 나눔 폰트 시리즈는 별도로 로드해야 합니다. **에디터 페이지와 Viewer 페이지 모두**에 적용해야 WYSIWYG이 보장됩니다.
98
+
99
+ 이 패키지는 두 가지 방식으로 폰트 로드를 지원합니다.
100
+
101
+ ### 방법 A: React 컴포넌트
102
+
103
+ `EditorFontStylesheets` 컴포넌트를 `<head>` 안에 렌더링합니다.
104
+
105
+ **Next.js App Router (`layout.tsx`)**
106
+
107
+ ```tsx
108
+ import { EditorFontStylesheets } from "@junbyeol/tiptap-editor";
109
+
110
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
111
+ return (
112
+ <html>
113
+ <head>
114
+ <EditorFontStylesheets />
115
+ </head>
116
+ <body>{children}</body>
117
+ </html>
118
+ );
119
+ }
120
+ ```
121
+
122
+ **Next.js Pages Router (`_document.tsx`)**
123
+
124
+ ```tsx
125
+ import { Html, Head, Main, NextScript } from "next/document";
126
+ import { EditorFontStylesheets } from "@junbyeol/tiptap-editor";
127
+
128
+ export default function Document() {
129
+ return (
130
+ <Html>
131
+ <Head>
132
+ <EditorFontStylesheets />
133
+ </Head>
134
+ <body>
135
+ <Main />
136
+ <NextScript />
137
+ </body>
138
+ </Html>
139
+ );
140
+ }
141
+ ```
142
+
143
+ ### 방법 B: 폰트 링크 데이터 직접 사용
144
+
145
+ `EDITOR_FONT_LINKS`를 직접 사용해 프레임워크에 맞게 삽입합니다.
146
+
147
+ ```tsx
148
+ import { EDITOR_FONT_LINKS } from "@junbyeol/tiptap-editor";
149
+
150
+ // EDITOR_FONT_LINKS 구조:
151
+ // [{ family: "Nanum Gothic", href: "https://fonts.googleapis.com/..." }, ...]
152
+
153
+ // 예: React Helmet
154
+ import { Helmet } from "react-helmet";
155
+
156
+ export default function App() {
157
+ return (
158
+ <>
159
+ <Helmet>
160
+ {EDITOR_FONT_LINKS.map((font) => (
161
+ <link key={font.family} rel="stylesheet" href={font.href} />
162
+ ))}
163
+ </Helmet>
164
+ {/* ... */}
165
+ </>
166
+ );
167
+ }
168
+ ```
169
+
73
170
  ## 로컬 개발
74
171
 
75
172
  ```bash
76
173
  # 의존성 설치
77
- yarn
174
+ pnpm install
78
175
 
79
- # 데모 앱 실행
80
- yarn dev
176
+ # 데모 앱 실행 (localhost:5173)
177
+ pnpm dev
81
178
 
82
179
  # 라이브러리 빌드
83
- yarn build:lib
180
+ pnpm build:lib
84
181
  ```
182
+
183
+ 데모 앱(`src/App.tsx`, `src/demo/*`)은 에디터 소스코드를 직접 import하지 않고, 빌드된
184
+ `dist/index.mjs`, `dist/style.css`를 alias로 사용합니다 ([vite.config.ts](./vite.config.ts) 참고).
185
+ 따라서 수정하는 파일 위치에 따라 반영 방식이 다릅니다.
186
+
187
+ - `src/App.tsx`, `src/demo/*` 등 **데모 전용 코드**: `pnpm dev`만 켜놓으면 HMR로 즉시 반영됩니다.
188
+ - `src/tiptap/*`, `src/components/*`, `src/styles/*`, `src/lib/*` 등 **에디터 라이브러리 소스**:
189
+ `dist/`를 다시 빌드해야 데모에 반영됩니다. 라이브러리를 수정하면서 데모로 바로 확인하려면
190
+ 터미널 두 개로 다음을 함께 띄워두세요.
191
+
192
+ ```bash
193
+ # 터미널 1: 라이브러리 소스 변경을 감지해 자동 재빌드
194
+ pnpm build:lib --watch
195
+
196
+ # 터미널 2: 데모 서버
197
+ pnpm dev
198
+ ```
199
+
200
+ 빌드 산출물을 alias로 물고 있어 HMR까지는 안 되므로, 재빌드 후 브라우저 새로고침이 필요할 수
201
+ 있습니다.