kc-plate-editor 0.2.1 → 0.3.0
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 +474 -57
- package/dist/components/editor/editor-base-kit.d.ts +7 -1
- package/dist/components/editor/editor-kit.d.ts +13 -1
- package/dist/components/editor/plate-editor.d.ts +45 -8
- package/dist/components/error-boundary.d.ts +57 -0
- package/dist/components/ui/configurable-toolbar.d.ts +6 -1
- package/dist/{index-9hvJpqmf.mjs → index-CKsqR2Kp.mjs} +1 -1
- package/dist/{index-C9pASjy7.js → index-Cjpf2atD.js} +1 -1
- package/dist/{index-CRj6ugBI.js → index-DXE99mkF.js} +326 -326
- package/dist/{index-BctaVSXR.mjs → index-Drawy4im.mjs} +26529 -26073
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.mjs +73 -36
- package/dist/lib/error-handler.d.ts +57 -0
- package/dist/lib/plugin-factory.d.ts +93 -0
- package/dist/lib/toolbar-presets.d.ts +63 -0
- package/dist/pages/FeatureShowcase.d.ts +1 -0
- package/dist/style.css +1 -1
- package/dist/types/editor-types.d.ts +28 -3
- package/dist/types/plugin-types.d.ts +27 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@ A powerful and customizable rich text editor built on [Plate](https://platejs.or
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
+
### 核心功能
|
|
7
8
|
- 🎨 **Rich Text Editing**: Support for headings, lists, tables, code blocks, and more
|
|
8
9
|
- 🤖 **AI-Powered**: Built-in AI assistance and copilot features
|
|
9
10
|
- 🎯 **Drag & Drop**: Intuitive drag-and-drop interface for blocks
|
|
@@ -12,10 +13,25 @@ A powerful and customizable rich text editor built on [Plate](https://platejs.or
|
|
|
12
13
|
- 💬 **Collaboration**: Comments and suggestions
|
|
13
14
|
- 🌐 **Internationalization**: Built-in i18n support (English & Chinese)
|
|
14
15
|
- 📱 **Responsive**: Adaptive toolbar for mobile and desktop
|
|
16
|
+
|
|
17
|
+
### 工具栏系统
|
|
15
18
|
- ⚙️ **Configurable Toolbar**: Flexible toolbar configuration system with visual configurator
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
+
- 🎯 **Toolbar Presets**: Pre-configured toolbar templates (Full, Basic, Minimal, Rich Text, Markdown, Blog, Document, Comment)
|
|
20
|
+
- 🔧 **Granular Control**: Fine-grained control over individual toolbar features
|
|
21
|
+
|
|
22
|
+
### 扩展功能
|
|
23
|
+
- 🔍 **Find & Replace**: Built-in text search and replace functionality
|
|
24
|
+
- 📊 **Word Count**: Real-time word, character, and paragraph counting
|
|
25
|
+
- 📑 **Outline Navigation**: Automatic document outline generation
|
|
26
|
+
- 📤 **Export**: Export to HTML, Markdown, PDF, and Image formats
|
|
27
|
+
- 🖥️ **Fullscreen Mode**: Distraction-free fullscreen editing
|
|
28
|
+
|
|
29
|
+
### 开发体验
|
|
30
|
+
- 🔌 **Extended API**: Comprehensive API with 30+ methods for content manipulation
|
|
31
|
+
- 🛡️ **Error Handling**: Unified error handling with error boundaries
|
|
32
|
+
- 📦 **TypeScript**: Full TypeScript support with comprehensive type definitions
|
|
33
|
+
- 🚀 **Performance**: Optimized rendering with React.memo and useMemo
|
|
34
|
+
- 🔧 **Plugin System**: Flexible plugin architecture with helper utilities
|
|
19
35
|
- ⚡ **Modern Stack**: Built with React 19, Vite, and Tailwind CSS
|
|
20
36
|
|
|
21
37
|
## Installation
|
|
@@ -89,38 +105,54 @@ function App() {
|
|
|
89
105
|
Configure exactly which toolbar features you need:
|
|
90
106
|
|
|
91
107
|
```tsx
|
|
92
|
-
import {
|
|
108
|
+
import {
|
|
109
|
+
PlateEditor,
|
|
110
|
+
MINIMAL_TOOLBAR,
|
|
111
|
+
BASIC_TOOLBAR,
|
|
112
|
+
RICH_TEXT_TOOLBAR,
|
|
113
|
+
MARKDOWN_TOOLBAR,
|
|
114
|
+
BLOG_TOOLBAR,
|
|
115
|
+
DOCUMENT_TOOLBAR,
|
|
116
|
+
COMMENT_TOOLBAR,
|
|
117
|
+
getToolbarPreset,
|
|
118
|
+
} from 'kc-plate-editor';
|
|
93
119
|
import type { ToolbarConfig } from 'kc-plate-editor';
|
|
94
120
|
|
|
95
121
|
function App() {
|
|
96
|
-
//
|
|
97
|
-
const minimalConfig: ToolbarConfig = {
|
|
98
|
-
history: true,
|
|
99
|
-
textFormat: ['bold', 'italic', 'underline'],
|
|
100
|
-
insert: ['link'],
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// Comment editor configuration
|
|
104
|
-
const commentConfig: ToolbarConfig = {
|
|
105
|
-
history: true,
|
|
106
|
-
textFormat: ['bold', 'italic'],
|
|
107
|
-
insert: ['link', 'emoji'],
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
// Full configuration (all features)
|
|
111
|
-
const fullConfig = createFullConfig();
|
|
112
|
-
|
|
122
|
+
// Use preset configurations
|
|
113
123
|
return (
|
|
114
124
|
<>
|
|
115
125
|
{/* Minimal editor */}
|
|
116
|
-
<PlateEditor toolbarConfig={
|
|
117
|
-
|
|
126
|
+
<PlateEditor toolbarConfig={MINIMAL_TOOLBAR} />
|
|
127
|
+
|
|
128
|
+
{/* Basic editor */}
|
|
129
|
+
<PlateEditor toolbarConfig={BASIC_TOOLBAR} />
|
|
130
|
+
|
|
131
|
+
{/* Rich text editor */}
|
|
132
|
+
<PlateEditor toolbarConfig={RICH_TEXT_TOOLBAR} />
|
|
133
|
+
|
|
134
|
+
{/* Markdown editor */}
|
|
135
|
+
<PlateEditor toolbarConfig={MARKDOWN_TOOLBAR} />
|
|
136
|
+
|
|
137
|
+
{/* Blog editor */}
|
|
138
|
+
<PlateEditor toolbarConfig={BLOG_TOOLBAR} />
|
|
139
|
+
|
|
140
|
+
{/* Document editor */}
|
|
141
|
+
<PlateEditor toolbarConfig={DOCUMENT_TOOLBAR} />
|
|
142
|
+
|
|
118
143
|
{/* Comment editor */}
|
|
119
|
-
<PlateEditor toolbarConfig={
|
|
120
|
-
|
|
121
|
-
{/*
|
|
122
|
-
<PlateEditor toolbarConfig={
|
|
123
|
-
|
|
144
|
+
<PlateEditor toolbarConfig={COMMENT_TOOLBAR} />
|
|
145
|
+
|
|
146
|
+
{/* Or use getToolbarPreset */}
|
|
147
|
+
<PlateEditor toolbarConfig={getToolbarPreset('minimal')} />
|
|
148
|
+
|
|
149
|
+
{/* Custom configuration */}
|
|
150
|
+
<PlateEditor toolbarConfig={{
|
|
151
|
+
history: true,
|
|
152
|
+
textFormat: ['bold', 'italic', 'underline'],
|
|
153
|
+
insert: ['link', 'image'],
|
|
154
|
+
}} />
|
|
155
|
+
|
|
124
156
|
{/* Default editor (all features) */}
|
|
125
157
|
<PlateEditor />
|
|
126
158
|
</>
|
|
@@ -181,12 +213,17 @@ function App() {
|
|
|
181
213
|
|------|------|---------|-------------|
|
|
182
214
|
| value | Value | - | Editor content (controlled) |
|
|
183
215
|
| onChange | (value: Value) => void | - | Content change callback |
|
|
184
|
-
| plugins |
|
|
216
|
+
| plugins | EditorPluginKit | - | Custom plugin list |
|
|
185
217
|
| toolbarConfig | ToolbarConfig | - | Toolbar configuration (see below) |
|
|
186
218
|
| className | string | - | Custom CSS class |
|
|
187
219
|
| disabled | boolean | false | Disable editor |
|
|
188
220
|
| readOnly | boolean | false | Read-only mode |
|
|
189
221
|
| autoFocus | boolean | false | Auto focus on mount |
|
|
222
|
+
| showToolbar | boolean | true | Show/hide toolbar |
|
|
223
|
+
| toolbarSticky | boolean | true | Make toolbar sticky |
|
|
224
|
+
| mode | 'edit' \| 'view' \| 'suggestion' | 'edit' | Editor mode |
|
|
225
|
+
| onModifiedChange | (isModified: boolean) => void | - | Modified state callback |
|
|
226
|
+
| onFullscreenChange | (isFullscreen: boolean) => void | - | Fullscreen state callback |
|
|
190
227
|
|
|
191
228
|
### ToolbarConfig
|
|
192
229
|
|
|
@@ -197,14 +234,28 @@ interface ToolbarConfig {
|
|
|
197
234
|
color?: boolean | ('textColor' | 'backgroundColor' | 'highlight')[];
|
|
198
235
|
align?: boolean | ('left' | 'center' | 'right' | 'justify')[];
|
|
199
236
|
list?: boolean | ('bulleted' | 'numbered' | 'todo')[];
|
|
200
|
-
insert?: boolean | ('link' | 'image' | 'video' | 'table' | 'emoji' | 'equation')[];
|
|
237
|
+
insert?: boolean | ('link' | 'image' | 'video' | 'audio' | 'file' | 'table' | 'emoji' | 'equation')[];
|
|
201
238
|
advanced?: boolean | ('ai' | 'comment' | 'export' | 'import')[];
|
|
202
239
|
typography?: boolean | ('fontSize' | 'lineHeight')[];
|
|
203
240
|
extraFormat?: boolean | ('superscript' | 'subscript' | 'keyboard')[];
|
|
204
241
|
blockOps?: boolean | ('indent' | 'outdent' | 'toggle')[];
|
|
242
|
+
turnInto?: boolean;
|
|
205
243
|
}
|
|
206
244
|
```
|
|
207
245
|
|
|
246
|
+
**Toolbar Presets:**
|
|
247
|
+
|
|
248
|
+
| Preset | Description | Use Case |
|
|
249
|
+
|--------|-------------|----------|
|
|
250
|
+
| `FULL_TOOLBAR` | All features enabled | Full-featured editor |
|
|
251
|
+
| `BASIC_TOOLBAR` | Common text editing features | General purpose editing |
|
|
252
|
+
| `MINIMAL_TOOLBAR` | Minimal feature set | Simple text input |
|
|
253
|
+
| `RICH_TEXT_TOOLBAR` | Rich formatting features | Document editing |
|
|
254
|
+
| `MARKDOWN_TOOLBAR` | Markdown-focused features | Markdown editing |
|
|
255
|
+
| `BLOG_TOOLBAR` | Blog post editing features | Blog/article writing |
|
|
256
|
+
| `DOCUMENT_TOOLBAR` | Formal document features | Professional documents |
|
|
257
|
+
| `COMMENT_TOOLBAR` | Comment/annotation features | Comments and notes |
|
|
258
|
+
|
|
208
259
|
**Examples:**
|
|
209
260
|
|
|
210
261
|
```typescript
|
|
@@ -221,33 +272,73 @@ interface ToolbarConfig {
|
|
|
221
272
|
insert: ['link', 'image'],
|
|
222
273
|
list: true
|
|
223
274
|
}
|
|
275
|
+
|
|
276
|
+
// Use preset
|
|
277
|
+
import { MARKDOWN_TOOLBAR } from 'kc-plate-editor';
|
|
278
|
+
<PlateEditor toolbarConfig={MARKDOWN_TOOLBAR} />
|
|
224
279
|
```
|
|
225
280
|
|
|
226
281
|
### PlateEditorRef Methods
|
|
227
282
|
|
|
283
|
+
The editor ref provides 30+ methods for comprehensive content manipulation:
|
|
284
|
+
|
|
228
285
|
```typescript
|
|
229
286
|
interface PlateEditorRef {
|
|
230
|
-
// Content
|
|
231
|
-
getContent: () => Value;
|
|
232
|
-
setContent: (content: Value) => void;
|
|
233
|
-
resetContent: () => void;
|
|
234
|
-
getEditor: () =>
|
|
235
|
-
|
|
236
|
-
// Markdown
|
|
237
|
-
getMarkdown: () => string;
|
|
238
|
-
setMarkdown: (markdown: string) => void;
|
|
239
|
-
|
|
240
|
-
// HTML
|
|
241
|
-
getHtml: () => Promise<string>;
|
|
242
|
-
setHtml: (html: string) => void;
|
|
243
|
-
|
|
244
|
-
// Text
|
|
245
|
-
getText: () => string;
|
|
246
|
-
isEmpty: () => boolean;
|
|
247
|
-
|
|
248
|
-
// Editor
|
|
249
|
-
focus: () => void;
|
|
250
|
-
blur: () => void;
|
|
287
|
+
// ========== Content Management ==========
|
|
288
|
+
getContent: () => Value; // Get editor content (JSON)
|
|
289
|
+
setContent: (content: Value) => void; // Set editor content
|
|
290
|
+
resetContent: () => void; // Reset to initial content
|
|
291
|
+
getEditor: () => TPlateEditor; // Get editor instance (advanced)
|
|
292
|
+
|
|
293
|
+
// ========== Markdown Support ==========
|
|
294
|
+
getMarkdown: () => string; // Export as Markdown
|
|
295
|
+
setMarkdown: (markdown: string) => void; // Load from Markdown
|
|
296
|
+
|
|
297
|
+
// ========== HTML Support ==========
|
|
298
|
+
getHtml: () => Promise<string>; // Export as HTML
|
|
299
|
+
setHtml: (html: string) => void; // Load from HTML
|
|
300
|
+
|
|
301
|
+
// ========== Text Utilities ==========
|
|
302
|
+
getText: () => string; // Get plain text
|
|
303
|
+
isEmpty: () => boolean; // Check if empty
|
|
304
|
+
|
|
305
|
+
// ========== Editor Control ==========
|
|
306
|
+
focus: () => void; // Focus editor
|
|
307
|
+
blur: () => void; // Blur editor
|
|
308
|
+
|
|
309
|
+
// ========== Modified State ==========
|
|
310
|
+
isModified: () => boolean; // Check if content is modified
|
|
311
|
+
resetModifiedState: () => void; // Reset modified state
|
|
312
|
+
|
|
313
|
+
// ========== Content Insertion ==========
|
|
314
|
+
insertText: (text: string) => void; // Insert text
|
|
315
|
+
insertMarkdown: (markdown: string) => void; // Insert Markdown content
|
|
316
|
+
toggleMark: (mark: string) => void; // Toggle mark (bold, italic, etc.)
|
|
317
|
+
insertLink: (url: string, text?: string) => void; // Insert link
|
|
318
|
+
insertImage: (url: string) => void; // Insert image
|
|
319
|
+
|
|
320
|
+
// ========== History Operations ==========
|
|
321
|
+
undo: () => void; // Undo
|
|
322
|
+
redo: () => void; // Redo
|
|
323
|
+
|
|
324
|
+
// ========== Export Functions ==========
|
|
325
|
+
exportAsHtml: (filename?: string) => Promise<void>; // Export as HTML file
|
|
326
|
+
exportAsMarkdown: (filename?: string) => Promise<void>; // Export as Markdown file
|
|
327
|
+
exportAsPdf: (filename?: string) => Promise<void>; // Export as PDF file
|
|
328
|
+
exportAsImage: (filename?: string) => Promise<void>; // Export as Image file
|
|
329
|
+
|
|
330
|
+
// ========== Find & Replace ==========
|
|
331
|
+
find: (searchText: string, options?: FindOptions) => MatchPosition[];
|
|
332
|
+
replace: (searchText: string, replaceText: string, options?: ReplaceOptions) => number;
|
|
333
|
+
|
|
334
|
+
// ========== Document Analysis ==========
|
|
335
|
+
getOutline: () => OutlineItem[]; // Get document outline
|
|
336
|
+
getWordCount: () => WordCountResult; // Get word count statistics
|
|
337
|
+
|
|
338
|
+
// ========== Fullscreen Control ==========
|
|
339
|
+
enterFullscreen: () => Promise<void>; // Enter fullscreen mode
|
|
340
|
+
exitFullscreen: () => Promise<void>; // Exit fullscreen mode
|
|
341
|
+
isFullscreen: () => boolean; // Check fullscreen state
|
|
251
342
|
}
|
|
252
343
|
```
|
|
253
344
|
|
|
@@ -265,20 +356,346 @@ interface EditorConfig {
|
|
|
265
356
|
}
|
|
266
357
|
```
|
|
267
358
|
|
|
359
|
+
### Exported Types
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// Core types
|
|
363
|
+
import type {
|
|
364
|
+
PlateEditorProps,
|
|
365
|
+
PlateEditorRef,
|
|
366
|
+
EditorPluginKit,
|
|
367
|
+
EditorPlugin,
|
|
368
|
+
PluginKitOptions,
|
|
369
|
+
PluginKitFactory,
|
|
370
|
+
} from 'kc-plate-editor';
|
|
371
|
+
|
|
372
|
+
// Toolbar types
|
|
373
|
+
import type {
|
|
374
|
+
ToolbarConfig,
|
|
375
|
+
ToolbarFeatureId,
|
|
376
|
+
ToolbarGroupId,
|
|
377
|
+
ToolbarPresetName,
|
|
378
|
+
ToolbarFeature,
|
|
379
|
+
ToolbarGroup,
|
|
380
|
+
} from 'kc-plate-editor';
|
|
381
|
+
|
|
382
|
+
// Editor types
|
|
383
|
+
import type {
|
|
384
|
+
EditorMode,
|
|
385
|
+
EditorValue,
|
|
386
|
+
FindOptions,
|
|
387
|
+
ReplaceOptions,
|
|
388
|
+
WordCountResult,
|
|
389
|
+
OutlineItem,
|
|
390
|
+
MatchPosition,
|
|
391
|
+
} from 'kc-plate-editor';
|
|
392
|
+
|
|
393
|
+
// Error handling types
|
|
394
|
+
import type {
|
|
395
|
+
EditorErrorBoundaryProps,
|
|
396
|
+
ErrorHandlerConfig,
|
|
397
|
+
} from 'kc-plate-editor';
|
|
398
|
+
|
|
399
|
+
// Config types
|
|
400
|
+
import type {
|
|
401
|
+
EditorConfig,
|
|
402
|
+
ConfigProviderProps,
|
|
403
|
+
I18nProviderProps,
|
|
404
|
+
Locale,
|
|
405
|
+
LocaleMessages,
|
|
406
|
+
} from 'kc-plate-editor';
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Exported Utilities
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
// Plugin utilities
|
|
413
|
+
import {
|
|
414
|
+
createPluginFactory,
|
|
415
|
+
mergePluginKits,
|
|
416
|
+
filterPluginKit,
|
|
417
|
+
replacePlugin,
|
|
418
|
+
insertPluginBefore,
|
|
419
|
+
insertPluginAfter,
|
|
420
|
+
} from 'kc-plate-editor';
|
|
421
|
+
|
|
422
|
+
// Toolbar utilities
|
|
423
|
+
import {
|
|
424
|
+
TOOLBAR_FEATURES,
|
|
425
|
+
getAllFeatures,
|
|
426
|
+
getFeaturesByGroup,
|
|
427
|
+
getFeatureById,
|
|
428
|
+
isFeatureEnabled,
|
|
429
|
+
getEnabledFeatures,
|
|
430
|
+
createFullConfig,
|
|
431
|
+
createMinimalConfig,
|
|
432
|
+
getToolbarPreset,
|
|
433
|
+
} from 'kc-plate-editor';
|
|
434
|
+
|
|
435
|
+
// Document utilities
|
|
436
|
+
import {
|
|
437
|
+
findText,
|
|
438
|
+
replaceText,
|
|
439
|
+
getWordCount,
|
|
440
|
+
getOutline,
|
|
441
|
+
exportAsHtml,
|
|
442
|
+
exportAsMarkdown,
|
|
443
|
+
exportAsPdf,
|
|
444
|
+
exportAsImage,
|
|
445
|
+
enterFullscreen,
|
|
446
|
+
exitFullscreen,
|
|
447
|
+
isFullscreen,
|
|
448
|
+
} from 'kc-plate-editor';
|
|
449
|
+
|
|
450
|
+
// Error handling utilities
|
|
451
|
+
import {
|
|
452
|
+
EditorError,
|
|
453
|
+
EditorErrorType,
|
|
454
|
+
handleEditorError,
|
|
455
|
+
configureErrorHandler,
|
|
456
|
+
safeExecute,
|
|
457
|
+
withErrorBoundary,
|
|
458
|
+
getFriendlyErrorMessage,
|
|
459
|
+
} from 'kc-plate-editor';
|
|
460
|
+
|
|
461
|
+
// Config generation utilities
|
|
462
|
+
import {
|
|
463
|
+
generateConfig,
|
|
464
|
+
generateCode,
|
|
465
|
+
generateTypeScriptCode,
|
|
466
|
+
generateJavaScriptCode,
|
|
467
|
+
generateJSON,
|
|
468
|
+
getCodeFormatName,
|
|
469
|
+
} from 'kc-plate-editor';
|
|
470
|
+
```
|
|
471
|
+
|
|
268
472
|
## Advanced Usage
|
|
269
473
|
|
|
474
|
+
### Error Handling
|
|
475
|
+
|
|
476
|
+
Wrap your editor with error boundary for better error handling:
|
|
477
|
+
|
|
478
|
+
```tsx
|
|
479
|
+
import { PlateEditor, EditorErrorBoundary } from 'kc-plate-editor';
|
|
480
|
+
|
|
481
|
+
function App() {
|
|
482
|
+
return (
|
|
483
|
+
<EditorErrorBoundary>
|
|
484
|
+
<PlateEditor />
|
|
485
|
+
</EditorErrorBoundary>
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Or use HOC
|
|
490
|
+
import { withErrorBoundary } from 'kc-plate-editor';
|
|
491
|
+
|
|
492
|
+
const SafeEditor = withErrorBoundary(PlateEditor);
|
|
493
|
+
|
|
494
|
+
function App() {
|
|
495
|
+
return <SafeEditor />;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Configure global error handler
|
|
499
|
+
import { configureErrorHandler } from 'kc-plate-editor';
|
|
500
|
+
|
|
501
|
+
configureErrorHandler({
|
|
502
|
+
logToConsole: true,
|
|
503
|
+
onError: (error) => {
|
|
504
|
+
// Send to error tracking service
|
|
505
|
+
console.error('Editor error:', error);
|
|
506
|
+
},
|
|
507
|
+
});
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Find & Replace
|
|
511
|
+
|
|
512
|
+
```tsx
|
|
513
|
+
import { useRef } from 'react';
|
|
514
|
+
import { PlateEditor } from 'kc-plate-editor';
|
|
515
|
+
import type { PlateEditorRef } from 'kc-plate-editor';
|
|
516
|
+
|
|
517
|
+
function App() {
|
|
518
|
+
const editorRef = useRef<PlateEditorRef>(null);
|
|
519
|
+
|
|
520
|
+
const handleFind = () => {
|
|
521
|
+
const matches = editorRef.current?.find('search text', {
|
|
522
|
+
caseSensitive: false,
|
|
523
|
+
});
|
|
524
|
+
console.log(`Found ${matches?.length} matches`);
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
const handleReplace = () => {
|
|
528
|
+
const count = editorRef.current?.replace(
|
|
529
|
+
'old text',
|
|
530
|
+
'new text',
|
|
531
|
+
{ replaceAll: true, caseSensitive: false }
|
|
532
|
+
);
|
|
533
|
+
console.log(`Replaced ${count} occurrences`);
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
return (
|
|
537
|
+
<>
|
|
538
|
+
<button onClick={handleFind}>Find</button>
|
|
539
|
+
<button onClick={handleReplace}>Replace All</button>
|
|
540
|
+
<PlateEditor ref={editorRef} />
|
|
541
|
+
</>
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Word Count & Outline
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
import { useRef, useState } from 'react';
|
|
550
|
+
import { PlateEditor } from 'kc-plate-editor';
|
|
551
|
+
import type { PlateEditorRef, WordCountResult, OutlineItem } from 'kc-plate-editor';
|
|
552
|
+
|
|
553
|
+
function App() {
|
|
554
|
+
const editorRef = useRef<PlateEditorRef>(null);
|
|
555
|
+
const [wordCount, setWordCount] = useState<WordCountResult | null>(null);
|
|
556
|
+
const [outline, setOutline] = useState<OutlineItem[]>([]);
|
|
557
|
+
|
|
558
|
+
const updateStats = () => {
|
|
559
|
+
const count = editorRef.current?.getWordCount();
|
|
560
|
+
const outline = editorRef.current?.getOutline();
|
|
561
|
+
setWordCount(count || null);
|
|
562
|
+
setOutline(outline || []);
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
return (
|
|
566
|
+
<>
|
|
567
|
+
<button onClick={updateStats}>Update Stats</button>
|
|
568
|
+
|
|
569
|
+
{wordCount && (
|
|
570
|
+
<div>
|
|
571
|
+
<p>Words: {wordCount.words}</p>
|
|
572
|
+
<p>Characters: {wordCount.charactersWithSpaces}</p>
|
|
573
|
+
<p>Paragraphs: {wordCount.paragraphs}</p>
|
|
574
|
+
</div>
|
|
575
|
+
)}
|
|
576
|
+
|
|
577
|
+
{outline.length > 0 && (
|
|
578
|
+
<nav>
|
|
579
|
+
<h3>Outline</h3>
|
|
580
|
+
<ul>
|
|
581
|
+
{outline.map((item) => (
|
|
582
|
+
<li key={item.id} style={{ marginLeft: `${item.depth * 20}px` }}>
|
|
583
|
+
{item.title}
|
|
584
|
+
</li>
|
|
585
|
+
))}
|
|
586
|
+
</ul>
|
|
587
|
+
</nav>
|
|
588
|
+
)}
|
|
589
|
+
|
|
590
|
+
<PlateEditor ref={editorRef} />
|
|
591
|
+
</>
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Export Functions
|
|
597
|
+
|
|
598
|
+
```tsx
|
|
599
|
+
import { useRef } from 'react';
|
|
600
|
+
import { PlateEditor } from 'kc-plate-editor';
|
|
601
|
+
import type { PlateEditorRef } from 'kc-plate-editor';
|
|
602
|
+
|
|
603
|
+
function App() {
|
|
604
|
+
const editorRef = useRef<PlateEditorRef>(null);
|
|
605
|
+
|
|
606
|
+
const handleExport = async (format: 'html' | 'markdown' | 'pdf' | 'image') => {
|
|
607
|
+
switch (format) {
|
|
608
|
+
case 'html':
|
|
609
|
+
await editorRef.current?.exportAsHtml('document.html');
|
|
610
|
+
break;
|
|
611
|
+
case 'markdown':
|
|
612
|
+
await editorRef.current?.exportAsMarkdown('document.md');
|
|
613
|
+
break;
|
|
614
|
+
case 'pdf':
|
|
615
|
+
await editorRef.current?.exportAsPdf('document.pdf');
|
|
616
|
+
break;
|
|
617
|
+
case 'image':
|
|
618
|
+
await editorRef.current?.exportAsImage('document.png');
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
return (
|
|
624
|
+
<>
|
|
625
|
+
<button onClick={() => handleExport('html')}>Export HTML</button>
|
|
626
|
+
<button onClick={() => handleExport('markdown')}>Export Markdown</button>
|
|
627
|
+
<button onClick={() => handleExport('pdf')}>Export PDF</button>
|
|
628
|
+
<button onClick={() => handleExport('image')}>Export Image</button>
|
|
629
|
+
<PlateEditor ref={editorRef} />
|
|
630
|
+
</>
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Fullscreen Mode
|
|
636
|
+
|
|
637
|
+
```tsx
|
|
638
|
+
import { useRef } from 'react';
|
|
639
|
+
import { PlateEditor } from 'kc-plate-editor';
|
|
640
|
+
import type { PlateEditorRef } from 'kc-plate-editor';
|
|
641
|
+
|
|
642
|
+
function App() {
|
|
643
|
+
const editorRef = useRef<PlateEditorRef>(null);
|
|
644
|
+
|
|
645
|
+
const toggleFullscreen = async () => {
|
|
646
|
+
if (editorRef.current?.isFullscreen()) {
|
|
647
|
+
await editorRef.current?.exitFullscreen();
|
|
648
|
+
} else {
|
|
649
|
+
await editorRef.current?.enterFullscreen();
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
return (
|
|
654
|
+
<>
|
|
655
|
+
<button onClick={toggleFullscreen}>Toggle Fullscreen</button>
|
|
656
|
+
<PlateEditor
|
|
657
|
+
ref={editorRef}
|
|
658
|
+
onFullscreenChange={(isFullscreen) => {
|
|
659
|
+
console.log('Fullscreen:', isFullscreen);
|
|
660
|
+
}}
|
|
661
|
+
/>
|
|
662
|
+
</>
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
```
|
|
666
|
+
|
|
270
667
|
### Custom Plugins
|
|
271
668
|
|
|
272
669
|
```tsx
|
|
273
|
-
import {
|
|
670
|
+
import {
|
|
671
|
+
PlateEditor,
|
|
672
|
+
BaseEditorKit,
|
|
673
|
+
mergePluginKits,
|
|
674
|
+
filterPluginKit,
|
|
675
|
+
replacePlugin,
|
|
676
|
+
} from 'kc-plate-editor';
|
|
274
677
|
import { MyCustomPlugin } from './plugins';
|
|
275
678
|
|
|
276
|
-
const customPlugins = [
|
|
277
|
-
...BaseEditorKit,
|
|
278
|
-
MyCustomPlugin,
|
|
279
|
-
];
|
|
280
|
-
|
|
281
679
|
function App() {
|
|
680
|
+
// Merge plugin kits
|
|
681
|
+
const customPlugins = mergePluginKits(
|
|
682
|
+
BaseEditorKit,
|
|
683
|
+
[MyCustomPlugin]
|
|
684
|
+
);
|
|
685
|
+
|
|
686
|
+
// Filter plugins
|
|
687
|
+
const filteredPlugins = filterPluginKit(
|
|
688
|
+
BaseEditorKit,
|
|
689
|
+
(plugin) => plugin.key !== 'unwanted-plugin'
|
|
690
|
+
);
|
|
691
|
+
|
|
692
|
+
// Replace a plugin
|
|
693
|
+
const updatedPlugins = replacePlugin(
|
|
694
|
+
BaseEditorKit,
|
|
695
|
+
'old-plugin',
|
|
696
|
+
MyCustomPlugin
|
|
697
|
+
);
|
|
698
|
+
|
|
282
699
|
return <PlateEditor plugins={customPlugins} />;
|
|
283
700
|
}
|
|
284
701
|
```
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { Value } from 'platejs';
|
|
2
2
|
import { TPlateEditor } from 'platejs/react';
|
|
3
|
-
|
|
3
|
+
import { EditorPluginKit } from '../../types/plugin-types';
|
|
4
|
+
/**
|
|
5
|
+
* 完整的编辑器插件集合
|
|
6
|
+
* 包含所有功能插件,适用于全功能编辑器
|
|
7
|
+
*/
|
|
8
|
+
export declare const EditorKit: EditorPluginKit;
|
|
9
|
+
/**
|
|
10
|
+
* 编辑器实例类型
|
|
11
|
+
*/
|
|
4
12
|
export type MyEditor = TPlateEditor<Value, (typeof EditorKit)[number]>;
|
|
13
|
+
/**
|
|
14
|
+
* 获取编辑器实例的 Hook
|
|
15
|
+
* @returns 编辑器实例
|
|
16
|
+
*/
|
|
5
17
|
export declare const useEditor: () => MyEditor;
|