@cepoltd/lpeditor 0.9.0 → 0.9.2
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 +127 -131
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,181 +1,177 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @cepoltd/lpeditor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lexical 기반의 A4 페이지네이션 에디터. Google Docs / MS Word 스타일의 페이지 분리, 템플릿, 인장, Export 등을 지원합니다.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 설치
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install @cepoltd/lpeditor
|
|
9
|
+
```
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
실시간 협업 기능은 선택적으로 동적 import하여 사용할 수 있습니다.
|
|
11
|
+
## 빠른 시작
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
```tsx
|
|
14
|
+
import { LpEditor } from '@cepoltd/lpeditor';
|
|
15
|
+
import '@cepoltd/lpeditor/style.css';
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
function App() {
|
|
18
|
+
return <LpEditor />;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
- ✅ **Multiple Page Formats**: A4, Letter, Legal
|
|
18
|
-
- ✅ **Portrait/Landscape Orientation**: Flexible page orientation
|
|
19
|
-
- ✅ **Smart Content Management**: Only moves newly added content to next page (preserves existing content)
|
|
20
|
-
- ✅ **Manual Page Breaks**: Ctrl+Enter to insert manual page breaks
|
|
21
|
-
- ✅ **Rich Text Formatting**: Bold, Italic, Underline, H1-H3 headings
|
|
22
|
-
- ✅ **Template System**: Meta fields, approval lines, stamps
|
|
23
|
-
- ✅ **Real-time Collaboration**: Optional Yjs-based collaboration (separate bundle)
|
|
24
|
-
- ✅ **Comment System**: Built-in commenting without Yjs
|
|
25
|
-
- ✅ **Print Support**: Optimized for printing
|
|
26
|
-
- ✅ **Performance Optimized**: Debounced pagination with requestAnimationFrame
|
|
27
|
-
- ✅ **Bundle Optimization**: Tree-shaking friendly, code-splitting ready
|
|
22
|
+
## 주요 기능
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
- **A4 페이지네이션** — 자동 페이지 분리, A4/Letter/Legal 포맷, 세로/가로 방향
|
|
25
|
+
- **문서 모드** — EDIT (편집) / INPUT (입력) / VIEW (읽기 전용)
|
|
26
|
+
- **리치 텍스트** — Bold, Italic, Underline, 제목(H1-H6), 리스트, 테이블
|
|
27
|
+
- **템플릿 시스템** — 메타 필드, 변수 바인딩, 인장/서명
|
|
28
|
+
- **Export / Import** — PDF, DOCX, HTML 내보내기 및 가져오기
|
|
29
|
+
- **문서 아웃라인** — 목차 자동 생성
|
|
30
|
+
- **댓글** — 내장 코멘트 시스템
|
|
31
|
+
- **폰트 관리** — 커스텀 폰트 지원
|
|
32
|
+
- **인쇄 최적화** — 페이지 단위 인쇄
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
/src
|
|
33
|
-
/lib # Library source (distributable)
|
|
34
|
-
/plugins # Lexical plugins
|
|
35
|
-
/pagination # 📁 All pagination-related code
|
|
36
|
-
paginationCore.ts # 🔒 CORE: Pagination logic - DO NOT MODIFY
|
|
37
|
-
PageNode.ts # Page container node
|
|
38
|
-
PageBreakNode.ts # Manual page break node
|
|
39
|
-
PageManagerPlugin.tsx # Main pagination manager
|
|
40
|
-
PageToolbarPlugin.tsx # Page settings toolbar
|
|
41
|
-
index.ts # Pagination exports
|
|
42
|
-
FormattingToolbarPlugin.tsx # Text formatting toolbar
|
|
43
|
-
/components # React components
|
|
44
|
-
PaginatedEditor.tsx # Main editor component
|
|
45
|
-
/styles # CSS styles
|
|
46
|
-
editor.css # Editor styles
|
|
47
|
-
index.ts # Main library export
|
|
48
|
-
|
|
49
|
-
/app # Demo application
|
|
50
|
-
App.tsx # Demo app entry
|
|
51
|
-
|
|
52
|
-
/styles # Global styles
|
|
53
|
-
fonts.css
|
|
54
|
-
index.css
|
|
55
|
-
tailwind.css
|
|
56
|
-
theme.css
|
|
57
|
-
```
|
|
34
|
+
## 사용 예제
|
|
58
35
|
|
|
59
|
-
|
|
36
|
+
### 문서 모드 전환
|
|
60
37
|
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
|
|
38
|
+
```tsx
|
|
39
|
+
import { useState } from 'react';
|
|
40
|
+
import { LpEditor } from '@cepoltd/lpeditor';
|
|
41
|
+
import type { DocumentMode } from '@cepoltd/lpeditor';
|
|
42
|
+
|
|
43
|
+
function App() {
|
|
44
|
+
const [mode, setMode] = useState<DocumentMode>('EDIT');
|
|
64
45
|
|
|
65
|
-
|
|
46
|
+
return (
|
|
47
|
+
<div>
|
|
48
|
+
<button onClick={() => setMode('EDIT')}>편집</button>
|
|
49
|
+
<button onClick={() => setMode('INPUT')}>입력</button>
|
|
50
|
+
<button onClick={() => setMode('VIEW')}>보기</button>
|
|
51
|
+
|
|
52
|
+
<LpEditor
|
|
53
|
+
documentMode={mode}
|
|
54
|
+
onModeChange={(newMode) => setMode(newMode)}
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
66
60
|
|
|
67
|
-
###
|
|
61
|
+
### 콘텐츠 변경 감지
|
|
68
62
|
|
|
69
63
|
```tsx
|
|
70
|
-
import {
|
|
64
|
+
import { LpEditor } from '@cepoltd/lpeditor';
|
|
71
65
|
|
|
72
66
|
function App() {
|
|
73
|
-
return
|
|
67
|
+
return (
|
|
68
|
+
<LpEditor
|
|
69
|
+
content="<h1>제목</h1><p>본문</p>"
|
|
70
|
+
onChange={(html, editorState) => {
|
|
71
|
+
console.log('HTML:', html);
|
|
72
|
+
console.log('JSON:', editorState.json);
|
|
73
|
+
console.log('Text:', editorState.text);
|
|
74
|
+
}}
|
|
75
|
+
debounceMs={500}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
74
78
|
}
|
|
75
79
|
```
|
|
76
80
|
|
|
77
|
-
###
|
|
81
|
+
### EditorAPI ref
|
|
78
82
|
|
|
79
83
|
```tsx
|
|
80
|
-
import {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const initialConfig = {
|
|
91
|
-
namespace: 'MyEditor',
|
|
92
|
-
nodes: [PageNode, PageBreakNode, /* ... other nodes */],
|
|
93
|
-
onError: console.error,
|
|
84
|
+
import { useRef } from 'react';
|
|
85
|
+
import { LpEditor } from '@cepoltd/lpeditor';
|
|
86
|
+
import type { EditorAPI } from '@cepoltd/lpeditor';
|
|
87
|
+
|
|
88
|
+
function App() {
|
|
89
|
+
const editorRef = useRef<EditorAPI>(null);
|
|
90
|
+
|
|
91
|
+
const save = async () => {
|
|
92
|
+
const doc = await editorRef.current?.getDocument();
|
|
93
|
+
console.log(doc?.metaFields, doc?.data, doc?.mode);
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
return (
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
onFormatChange={setPageFormat}
|
|
102
|
-
onOrientationChange={setPageOrientation}
|
|
103
|
-
/>
|
|
104
|
-
<FormattingToolbarPlugin />
|
|
105
|
-
{/* ... RichTextPlugin, etc. */}
|
|
106
|
-
<PageManagerPlugin
|
|
107
|
-
pageFormat="a4"
|
|
108
|
-
pageOrientation="portrait"
|
|
109
|
-
/>
|
|
110
|
-
</LexicalComposer>
|
|
97
|
+
<>
|
|
98
|
+
<button onClick={save}>저장</button>
|
|
99
|
+
<LpEditor ref={editorRef} documentMode="EDIT" />
|
|
100
|
+
</>
|
|
111
101
|
);
|
|
112
102
|
}
|
|
113
103
|
```
|
|
114
104
|
|
|
115
|
-
|
|
105
|
+
### Export (PDF / DOCX / HTML)
|
|
116
106
|
|
|
117
|
-
|
|
107
|
+
```tsx
|
|
108
|
+
import { LpEditor, useExportPlugin } from '@cepoltd/lpeditor';
|
|
118
109
|
|
|
119
|
-
|
|
110
|
+
function App() {
|
|
111
|
+
const { exportToPDF, exportToDocx, exportToHTML } = useExportPlugin();
|
|
120
112
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
113
|
+
return (
|
|
114
|
+
<div>
|
|
115
|
+
<button onClick={() => exportToPDF()}>PDF</button>
|
|
116
|
+
<button onClick={() => exportToDocx()}>DOCX</button>
|
|
117
|
+
<button onClick={() => exportToHTML()}>HTML</button>
|
|
118
|
+
<LpEditor />
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
125
123
|
|
|
126
|
-
|
|
124
|
+
## Props
|
|
127
125
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
| Prop | Type | Default | 설명 |
|
|
127
|
+
|------|------|---------|------|
|
|
128
|
+
| `documentMode` | `'EDIT' \| 'INPUT' \| 'VIEW'` | `'EDIT'` | 문서 모드 |
|
|
129
|
+
| `content` | `string` | — | 초기 HTML 콘텐츠 |
|
|
130
|
+
| `onChange` | `(html, editorState) => void` | — | 콘텐츠 변경 콜백 |
|
|
131
|
+
| `onContentChange` | `(html) => void` | — | 콘텐츠 변경 콜백 (legacy) |
|
|
132
|
+
| `onModeChange` | `(mode) => void` | — | 모드 변경 콜백 |
|
|
133
|
+
| `debounceMs` | `number` | `300` | onChange 디바운싱 (ms) |
|
|
134
|
+
| `ref` | `Ref<EditorAPI>` | — | 에디터 API 접근 |
|
|
132
135
|
|
|
133
|
-
|
|
136
|
+
## Exports
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
### 컴포넌트
|
|
139
|
+
`LpEditor` · `PaginatedEditor` (alias)
|
|
136
140
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- **Ctrl+U**: Underline
|
|
140
|
-
- **Ctrl+Enter**: Insert manual page break
|
|
141
|
+
### 타입
|
|
142
|
+
`EditorAPI` · `DocumentMode` · `MetaFieldDefinition` · `MetaTemplate` · `TemplateDefinition` · `VariableData` · `Comment` · `PageFormat` · `PageOrientation`
|
|
141
143
|
|
|
142
|
-
|
|
144
|
+
### 플러그인
|
|
145
|
+
`useExportPlugin` · `useImportPlugin` · `useTemplateAPI` · `EnhancedToolbarPlugin` · `FormattingToolbarPlugin` · `OutlinePlugin` · `CommentPlugin` · `FontPlugin` · `TablePlugin` · `VariablePlugin` · `SignatureStampPlugin`
|
|
143
146
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
```
|
|
147
|
+
### 페이지네이션
|
|
148
|
+
`PageNode` · `PageBreakNode` · `PageManagerPlugin` · `PageToolbarPlugin`
|
|
147
149
|
|
|
148
|
-
|
|
150
|
+
### 템플릿
|
|
151
|
+
`TemplatePlugin` · `TemplatePanel` · `StampButton` · `insertTemplate` · `templateRegistry` · `defaultTemplates`
|
|
149
152
|
|
|
150
|
-
|
|
151
|
-
npm run build
|
|
152
|
-
```
|
|
153
|
+
## 키보드 단축키
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
| 단축키 | 기능 |
|
|
156
|
+
|--------|------|
|
|
157
|
+
| `Ctrl+B` | 볼드 |
|
|
158
|
+
| `Ctrl+I` | 이탤릭 |
|
|
159
|
+
| `Ctrl+U` | 밑줄 |
|
|
160
|
+
| `Ctrl+Enter` | 수동 페이지 나누기 |
|
|
155
161
|
|
|
156
|
-
|
|
162
|
+
## Peer Dependencies
|
|
157
163
|
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"react": "18.3.1",
|
|
167
|
+
"react-dom": "18.3.1"
|
|
168
|
+
}
|
|
158
169
|
```
|
|
159
|
-
RootNode
|
|
160
|
-
└─ PageNode (physical page container)
|
|
161
|
-
├─ ParagraphNode
|
|
162
|
-
├─ HeadingNode
|
|
163
|
-
├─ PageBreakNode (manual page break)
|
|
164
|
-
└─ ... other content nodes
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Pagination Flow
|
|
168
|
-
|
|
169
|
-
1. User types content
|
|
170
|
-
2. `PageManagerPlugin` listens for content changes (debounced)
|
|
171
|
-
3. `managePagination()` checks all pages for overflow
|
|
172
|
-
4. `handlePageOverflow()` moves last child to next page if needed
|
|
173
|
-
5. Pages are renumbered automatically
|
|
174
170
|
|
|
175
|
-
##
|
|
171
|
+
## 라이선스
|
|
176
172
|
|
|
177
|
-
|
|
173
|
+
UNLICENSED
|
|
178
174
|
|
|
179
|
-
|
|
175
|
+
---
|
|
180
176
|
|
|
181
177
|
Built with [Lexical](https://lexical.dev/) by Meta
|
package/package.json
CHANGED