kc-plate-editor 0.5.5 → 0.5.8

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
@@ -8,7 +8,42 @@
8
8
 
9
9
  | 版本 | 状态 | 说明 |
10
10
  |------|------|------|
11
- | v0.5.0 | ✅ 已发布私服 | 当前稳定版本 |
11
+ | v0.5.8 | ✅ 最新版本 | 内容格式转换优化(官方 API) |
12
+ | v0.5.6 | ✅ 稳定版本 | 增强上传配置灵活性 |
13
+ | v0.5.5 | ✅ 稳定版本 | 快捷键保存、本地存储、目录跳转优化 |
14
+ | v0.5.0 | ✅ 已发布私服 | 基础稳定版本 |
15
+
16
+ ### v0.5.8 更新内容
17
+
18
+ - **内容格式转换** - 基于 Plate.js 官方 API 实现 JSON/HTML/Markdown 互转
19
+ - **统一内容接口** - 新增 `getContentAs()` 和 `setContentFrom()` 方法
20
+ - **官方 serializeHtml** - HTML 序列化使用官方静态渲染 API
21
+ - **官方 MarkdownPlugin** - Markdown 转换使用官方 `@platejs/markdown`
22
+ - **代码清理** - 移除旧的 DOM 清理方案,统一使用官方 API
23
+
24
+ ### v0.5.6 更新内容
25
+
26
+ - **增强上传配置** - 新增 `UploadConfig` 详细配置接口
27
+ - **增强 AI 配置** - 新增 `AIConfig` 详细配置接口
28
+ - **自定义上传函数** - 支持 `customUpload` 完全自定义上传逻辑
29
+ - **自定义 AI 函数** - 支持 `customCopilot` 和 `customCommand` 自定义 AI 逻辑
30
+ - **文件验证** - 支持 `maxSize` 和 `acceptTypes` 文件验证
31
+ - **额外表单数据** - 支持 `extraData` 添加额外表单字段
32
+ - **灵活响应解析** - 支持多种服务端响应格式
33
+ - **配置辅助函数** - 新增 `getUploadConfig`、`getAiConfig` 等辅助函数
34
+
35
+ ### v0.5.5 更新内容
36
+
37
+ - **快捷键保存** - 支持 `Ctrl+S` / `Cmd+S` 快捷键保存
38
+ - **本地存储** - 新增 `saveToLocalStorage()` 和 `clearLocalStorage()` 方法
39
+ - **目录跳转优化** - 修复目录点击跳转不准确的问题
40
+ - **onSave 回调** - 新增 `onSave` 属性用于处理快捷键保存事件
41
+
42
+ ### v0.5.4 更新内容
43
+
44
+ - 修复编辑器容器双滚动条问题
45
+ - 优化 `EditorContainer` 的 `demo` 变体高度设置
46
+ - 修复工具栏吸顶在嵌套滚动容器中失效的问题
12
47
 
13
48
  ### v0.5.0 更新内容
14
49
 
@@ -25,6 +60,7 @@
25
60
  - [特性](#特性)
26
61
  - [安装](#安装)
27
62
  - [快速开始](#快速开始)
63
+ - [集成注意事项](#集成注意事项) ⭐ **重要**
28
64
  - [工具栏配置](#工具栏配置)
29
65
  - [内容操作](#内容操作)
30
66
  - [导出功能](#导出功能)
@@ -171,6 +207,437 @@ function App() {
171
207
  }
172
208
  ```
173
209
 
210
+ ### 6. 高级上传配置 (v0.5.6+)
211
+
212
+ ```tsx
213
+ import { ConfigProvider, PlateEditor, type UploadConfig } from 'kc-plate-editor';
214
+
215
+ // 详细的上传配置
216
+ const uploadConfig: UploadConfig = {
217
+ url: '/api/upload', // 上传地址
218
+ fieldName: 'file', // 文件字段名
219
+ maxSize: 10 * 1024 * 1024, // 最大 10MB
220
+ acceptTypes: ['image/*', 'video/*', 'application/pdf'],
221
+ headers: {
222
+ 'X-Upload-Token': 'your-token',
223
+ },
224
+ extraData: {
225
+ category: 'document',
226
+ source: 'editor',
227
+ },
228
+ };
229
+
230
+ function App() {
231
+ return (
232
+ <ConfigProvider
233
+ config={{
234
+ baseURL: 'https://api.example.com', // API 基础地址
235
+ upload: uploadConfig,
236
+ locale: 'zh-CN',
237
+ }}
238
+ >
239
+ <PlateEditor />
240
+ </ConfigProvider>
241
+ );
242
+ }
243
+ ```
244
+
245
+ ### 7. 自定义上传函数
246
+
247
+ ```tsx
248
+ import { ConfigProvider, PlateEditor, type UploadResult } from 'kc-plate-editor';
249
+
250
+ // 完全自定义上传逻辑
251
+ async function customUpload(
252
+ file: File,
253
+ onProgress?: (progress: number) => void
254
+ ): Promise<UploadResult> {
255
+ const formData = new FormData();
256
+ formData.append('file', file);
257
+
258
+ // 使用你自己的上传逻辑
259
+ const response = await fetch('/api/my-upload', {
260
+ method: 'POST',
261
+ body: formData,
262
+ });
263
+
264
+ const result = await response.json();
265
+
266
+ return {
267
+ url: result.fileUrl,
268
+ name: file.name,
269
+ size: file.size,
270
+ type: file.type,
271
+ key: result.fileId,
272
+ };
273
+ }
274
+
275
+ function App() {
276
+ return (
277
+ <ConfigProvider
278
+ config={{
279
+ upload: {
280
+ customUpload, // 使用自定义上传函数
281
+ },
282
+ locale: 'zh-CN',
283
+ }}
284
+ >
285
+ <PlateEditor />
286
+ </ConfigProvider>
287
+ );
288
+ }
289
+ ```
290
+
291
+ ### 8. AI 配置 (v0.5.6+)
292
+
293
+ ```tsx
294
+ import { ConfigProvider, PlateEditor, type AIConfig } from 'kc-plate-editor';
295
+
296
+ // 详细的 AI 配置
297
+ const aiConfig: AIConfig = {
298
+ copilotUrl: '/api/ai/copilot', // Copilot 自动补全 API
299
+ commandUrl: '/api/ai/command', // AI 命令/对话 API
300
+ apiKey: 'your-api-key', // API 密钥
301
+ model: 'gpt-4', // 模型名称
302
+ headers: {
303
+ 'X-Custom-Header': 'value',
304
+ },
305
+ };
306
+
307
+ function App() {
308
+ return (
309
+ <ConfigProvider
310
+ config={{
311
+ baseURL: 'https://api.example.com',
312
+ ai: aiConfig,
313
+ locale: 'zh-CN',
314
+ }}
315
+ >
316
+ <PlateEditor />
317
+ </ConfigProvider>
318
+ );
319
+ }
320
+ ```
321
+
322
+ ---
323
+
324
+ ## 集成注意事项
325
+
326
+ > ⚠️ **重要**: 在将 kc-plate-editor 集成到现有项目时,请仔细阅读以下注意事项,避免常见问题。
327
+
328
+ ### 1. 全局样式冲突
329
+
330
+ **问题**: 项目中的全局 CSS 可能会影响编辑器的显示效果。
331
+
332
+ **常见冲突**:
333
+
334
+ ```css
335
+ /* ❌ 这些全局样式会破坏编辑器的列表显示 */
336
+ ul, ol {
337
+ list-style: none;
338
+ padding: 0;
339
+ margin: 0;
340
+ }
341
+
342
+ /* ❌ 这会影响编辑器内的链接样式 */
343
+ a {
344
+ text-decoration: none;
345
+ color: inherit;
346
+ }
347
+ ```
348
+
349
+ **解决方案**:
350
+
351
+ ```css
352
+ /* ✅ 方案1: 使用更具体的选择器,排除编辑器区域 */
353
+ ul:not([data-slate-node]), ol:not([data-slate-node]) {
354
+ list-style: none;
355
+ }
356
+
357
+ /* ✅ 方案2: 在编辑器容器内重置样式 */
358
+ [data-plate-editor-container] ul,
359
+ [data-plate-editor-container] ol {
360
+ list-style: revert;
361
+ padding: revert;
362
+ margin: revert;
363
+ }
364
+
365
+ /* ✅ 方案3: 直接注释掉全局样式(推荐) */
366
+ /* ul, ol { list-style: none; } */
367
+ ```
368
+
369
+ ### 2. 容器高度和滚动
370
+
371
+ **问题**: 编辑器需要明确的高度才能正确滚动。
372
+
373
+ ```tsx
374
+ // ❌ 错误:没有设置高度,编辑器会无限增长
375
+ <div>
376
+ <PlateEditor />
377
+ </div>
378
+
379
+ // ✅ 正确:设置固定高度或使用 flex 布局
380
+ <div style={{ height: 500 }}>
381
+ <PlateEditor />
382
+ </div>
383
+
384
+ // ✅ 正确:使用 flex 布局填充可用空间
385
+ <div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
386
+ <header>...</header>
387
+ <div style={{ flex: 1, overflow: 'hidden' }}>
388
+ <PlateEditor />
389
+ </div>
390
+ </div>
391
+ ```
392
+
393
+ **Ant Design Card 中使用**:
394
+
395
+ ```tsx
396
+ // ✅ 推荐配置:设置 body 的高度和 overflow
397
+ <Card
398
+ style={{ minHeight: 500 }}
399
+ styles={{
400
+ body: {
401
+ padding: 0,
402
+ height: 500,
403
+ display: 'flex',
404
+ flexDirection: 'column',
405
+ overflow: 'hidden' // 防止双滚动条
406
+ }
407
+ }}
408
+ >
409
+ <PlateEditor />
410
+ </Card>
411
+ ```
412
+
413
+ ### 3. 工具栏吸顶
414
+
415
+ **问题**: 工具栏吸顶需要正确的滚动容器。
416
+
417
+ ```tsx
418
+ // ❌ 错误:外层容器有 overflow: auto,会创建新的滚动上下文
419
+ <div style={{ overflow: 'auto', height: 500 }}>
420
+ <PlateEditor toolbarSticky={true} />
421
+ </div>
422
+
423
+ // ✅ 正确:外层容器使用 overflow: hidden
424
+ <div style={{ overflow: 'hidden', height: 500 }}>
425
+ <PlateEditor toolbarSticky={true} />
426
+ </div>
427
+ ```
428
+
429
+ **独立工具栏场景**:
430
+
431
+ ```tsx
432
+ // 使用 StandaloneToolbar 时,需要自己管理滚动容器
433
+ import { StandaloneToolbar, PlateEditor } from 'kc-plate-editor';
434
+
435
+ // 滚动容器
436
+ <div className="scroll-container" style={{ overflow: 'auto', height: 500 }}>
437
+ {/* 工具栏使用 CSS sticky */}
438
+ <div style={{ position: 'sticky', top: 0, zIndex: 50 }}>
439
+ <StandaloneToolbar config={config} editor={editor} sticky={false} />
440
+ </div>
441
+
442
+ <PlateEditor showToolbar={false} />
443
+ </div>
444
+ ```
445
+
446
+ ### 4. 快捷键保存
447
+
448
+ **v0.5.5 新增**: 支持 `Ctrl+S` / `Cmd+S` 快捷键保存。
449
+
450
+ ```tsx
451
+ <PlateEditor
452
+ // 方式1: 使用 onSave 回调处理保存逻辑
453
+ onSave={(content) => {
454
+ console.log('快捷键保存:', content);
455
+ // 调用 API 保存到服务器
456
+ saveToServer(content);
457
+ }}
458
+
459
+ // 方式2: 启用自动保存到 localStorage
460
+ autoSave={true}
461
+ autoSaveKey="my-editor-content"
462
+ autoSaveInterval={5000} // 5秒自动保存一次
463
+ />
464
+ ```
465
+
466
+ **清理本地存储**:
467
+
468
+ ```tsx
469
+ // 发布或退出时清理临时数据
470
+ const handlePublish = async () => {
471
+ await publishDocument();
472
+ editorRef.current?.clearLocalStorage();
473
+ };
474
+
475
+ const handleExit = () => {
476
+ editorRef.current?.clearLocalStorage();
477
+ navigate('/');
478
+ };
479
+ ```
480
+
481
+ ### 5. 目录跳转
482
+
483
+ **问题**: 目录点击跳转不到正确位置。
484
+
485
+ **原因**: 编辑器使用了嵌套滚动容器,`scrollIntoView` 可能无法正确工作。
486
+
487
+ **v0.5.5 已修复**: 目录跳转现在会自动查找正确的滚动容器。
488
+
489
+ ```tsx
490
+ // 如果仍有问题,确保编辑器容器结构正确
491
+ <div style={{ height: 500, overflow: 'hidden' }}>
492
+ <PlateEditor
493
+ showToc={true}
494
+ tocPosition="right"
495
+ tocWidth={240}
496
+ />
497
+ </div>
498
+ ```
499
+
500
+ ### 6. 表单集成
501
+
502
+ **在 Ant Design Form 中使用**:
503
+
504
+ ```tsx
505
+ import { Form, Input, Button } from 'antd';
506
+ import { PlateEditor, ConfigProvider, EditorErrorBoundary } from 'kc-plate-editor';
507
+
508
+ function ArticleForm() {
509
+ const editorRef = useRef<PlateEditorRef>(null);
510
+
511
+ const handleSubmit = async () => {
512
+ const content = editorRef.current?.getContent();
513
+ const markdown = editorRef.current?.getMarkdown();
514
+ const html = await editorRef.current?.getHtml();
515
+
516
+ // 提交到服务器
517
+ await submitArticle({ content, markdown, html });
518
+ };
519
+
520
+ return (
521
+ <Form onFinish={handleSubmit}>
522
+ <Form.Item label="标题" name="title">
523
+ <Input />
524
+ </Form.Item>
525
+
526
+ <Form.Item label="内容">
527
+ {/* 添加边框样式 */}
528
+ <div style={{ border: '1px solid #d9d9d9', borderRadius: 8, overflow: 'hidden' }}>
529
+ <ConfigProvider config={{ locale: 'zh-CN' }}>
530
+ <EditorErrorBoundary>
531
+ <PlateEditor
532
+ ref={editorRef}
533
+ toolbarConfig={BASIC_TOOLBAR}
534
+ toolbarSticky={false} // 表单中不需要吸顶
535
+ showSettings={false}
536
+ />
537
+ </EditorErrorBoundary>
538
+ </ConfigProvider>
539
+ </div>
540
+ </Form.Item>
541
+
542
+ <Button type="primary" htmlType="submit">提交</Button>
543
+ </Form>
544
+ );
545
+ }
546
+ ```
547
+
548
+ ### 7. 全屏编辑模式
549
+
550
+ **实现全屏沉浸式编辑**:
551
+
552
+ ```tsx
553
+ function FullScreenEditor() {
554
+ return (
555
+ <div style={{
556
+ height: '100vh',
557
+ display: 'flex',
558
+ flexDirection: 'column',
559
+ background: '#fff',
560
+ }}>
561
+ {/* 顶部导航栏 */}
562
+ <div style={{
563
+ padding: '8px 16px',
564
+ borderBottom: '1px solid #e8e8e8',
565
+ flexShrink: 0,
566
+ }}>
567
+ <span>文档标题</span>
568
+ <Button onClick={handleSave}>保存</Button>
569
+ </div>
570
+
571
+ {/* 编辑器区域 - flex: 1 填充剩余空间 */}
572
+ <div style={{ flex: 1, overflow: 'hidden' }}>
573
+ <PlateEditor
574
+ toolbarConfig={FULL_TOOLBAR}
575
+ toolbarSticky={true}
576
+ toolbarAlign="center"
577
+ contentMaxWidth={900}
578
+ showToc={true}
579
+ tocPosition="right"
580
+ autoFocus
581
+ />
582
+ </div>
583
+ </div>
584
+ );
585
+ }
586
+ ```
587
+
588
+ ### 8. 错误边界
589
+
590
+ **始终使用 EditorErrorBoundary 包裹编辑器**:
591
+
592
+ ```tsx
593
+ import { EditorErrorBoundary, PlateEditor } from 'kc-plate-editor';
594
+
595
+ // ✅ 推荐:使用错误边界防止编辑器崩溃影响整个页面
596
+ <EditorErrorBoundary>
597
+ <PlateEditor />
598
+ </EditorErrorBoundary>
599
+ ```
600
+
601
+ ### 9. 性能优化
602
+
603
+ **避免不必要的重渲染**:
604
+
605
+ ```tsx
606
+ // ❌ 错误:每次渲染都创建新的配置对象
607
+ <PlateEditor
608
+ toolbarConfig={{ ...FULL_TOOLBAR, history: false }}
609
+ />
610
+
611
+ // ✅ 正确:使用 useMemo 缓存配置
612
+ const toolbarConfig = useMemo(() => ({
613
+ ...FULL_TOOLBAR,
614
+ history: false,
615
+ }), []);
616
+
617
+ <PlateEditor toolbarConfig={toolbarConfig} />
618
+ ```
619
+
620
+ **预设切换时重新挂载编辑器**:
621
+
622
+ ```tsx
623
+ // 使用 key 强制重新挂载,确保工具栏配置正确应用
624
+ <PlateEditor
625
+ key={`editor-${activePreset}`}
626
+ toolbarConfig={getToolbarConfig()}
627
+ />
628
+ ```
629
+
630
+ ### 10. 常见问题排查
631
+
632
+ | 问题 | 可能原因 | 解决方案 |
633
+ |------|----------|----------|
634
+ | 列表没有项目符号 | 全局 CSS 重置了 list-style | 移除或修改全局样式 |
635
+ | 双滚动条 | 容器和编辑器都有 overflow | 外层使用 `overflow: hidden` |
636
+ | 工具栏不吸顶 | 滚动容器不正确 | 检查父容器的 overflow 设置 |
637
+ | 目录跳转失效 | 嵌套滚动容器 | 升级到 v0.5.5 |
638
+ | 快捷键无效 | 焦点不在编辑器 | 确保编辑器已聚焦 |
639
+ | 内容丢失 | 未保存就离开 | 使用 autoSave 或 onSave |
640
+
174
641
  ---
175
642
 
176
643
  ## 工具栏配置
@@ -345,49 +812,158 @@ const outline = editorRef.current?.getOutline();
345
812
 
346
813
  ### PlateEditorRef 方法
347
814
 
815
+ #### 内容管理
816
+
348
817
  | 方法 | 说明 | 返回值 |
349
818
  |------|------|--------|
350
819
  | `getContent()` | 获取编辑器内容 | `Value` |
351
820
  | `setContent(value)` | 设置编辑器内容 | `void` |
352
821
  | `resetContent()` | 重置为初始内容 | `void` |
822
+ | `getText()` | 获取纯文本内容 | `string` |
823
+ | `isEmpty()` | 检查编辑器是否为空 | `boolean` |
824
+
825
+ #### Markdown/HTML 转换
826
+
827
+ | 方法 | 说明 | 返回值 |
828
+ |------|------|--------|
353
829
  | `getMarkdown()` | 获取 Markdown | `string` |
354
830
  | `setMarkdown(md)` | 设置 Markdown | `void` |
355
831
  | `insertMarkdown(md)` | 插入 Markdown | `void` |
356
832
  | `getHtml()` | 获取 HTML | `Promise<string>` |
357
833
  | `setHtml(html)` | 设置 HTML | `void` |
834
+
835
+ #### 查找替换
836
+
837
+ | 方法 | 说明 | 返回值 |
838
+ |------|------|--------|
358
839
  | `find(text, options)` | 查找文本 | `MatchPosition[]` |
359
840
  | `replace(search, replace, options)` | 替换文本 | `number` |
841
+
842
+ #### 文档分析
843
+
844
+ | 方法 | 说明 | 返回值 |
845
+ |------|------|--------|
360
846
  | `getWordCount()` | 获取字数统计 | `WordCountResult` |
361
847
  | `getOutline()` | 获取文档大纲 | `OutlineItem[]` |
848
+
849
+ #### 导出功能
850
+
851
+ | 方法 | 说明 | 返回值 |
852
+ |------|------|--------|
362
853
  | `exportAsHtml(filename)` | 导出 HTML | `Promise<void>` |
363
854
  | `exportAsMarkdown(filename)` | 导出 Markdown | `Promise<void>` |
364
855
  | `exportAsPdf(filename)` | 导出 PDF | `Promise<void>` |
365
856
  | `exportAsImage(filename)` | 导出图片 | `Promise<void>` |
857
+
858
+ #### 插入操作
859
+
860
+ | 方法 | 说明 | 返回值 |
861
+ |------|------|--------|
366
862
  | `insertText(text)` | 插入文本 | `void` |
367
863
  | `insertLink(url, text)` | 插入链接 | `void` |
368
864
  | `insertImage(url)` | 插入图片 | `void` |
865
+
866
+ #### 格式控制
867
+
868
+ | 方法 | 说明 | 返回值 |
869
+ |------|------|--------|
369
870
  | `toggleMark(mark)` | 切换格式 | `void` |
370
871
  | `undo()` | 撤销 | `void` |
371
872
  | `redo()` | 重做 | `void` |
873
+
874
+ #### 编辑器控制
875
+
876
+ | 方法 | 说明 | 返回值 |
877
+ |------|------|--------|
372
878
  | `focus()` | 聚焦编辑器 | `void` |
373
879
  | `blur()` | 失焦编辑器 | `void` |
374
880
  | `getEditor()` | 获取底层编辑器实例 | `TPlateEditor` |
375
881
 
882
+ #### 修改状态
883
+
884
+ | 方法 | 说明 | 返回值 |
885
+ |------|------|--------|
886
+ | `isModified()` | 检查内容是否已修改 | `boolean` |
887
+ | `resetModifiedState()` | 重置修改状态 | `void` |
888
+
889
+ #### 工具栏/目录控制
890
+
891
+ | 方法 | 说明 | 返回值 |
892
+ |------|------|--------|
893
+ | `setToolbarVisible(visible)` | 设置工具栏可见性 | `void` |
894
+ | `setTocVisible(visible)` | 设置目录可见性 | `void` |
895
+
896
+ #### 本地存储 (v0.5.5+)
897
+
898
+ | 方法 | 说明 | 返回值 |
899
+ |------|------|--------|
900
+ | `saveToLocalStorage()` | 手动保存到 localStorage | `void` |
901
+ | `clearLocalStorage()` | 清理 localStorage 临时数据 | `void` |
902
+
903
+ #### 自动保存
904
+
905
+ | 方法 | 说明 | 返回值 |
906
+ |------|------|--------|
907
+ | `getAutoSaveState()` | 获取自动保存状态 | `AutoSaveState` |
908
+ | `saveNow()` | 立即触发保存 | `void` |
909
+ | `restoreAutoSave()` | 恢复自动保存的内容 | `Value \| null` |
910
+ | `clearAutoSave()` | 清除自动保存数据 | `void` |
911
+
376
912
  ### PlateEditorProps
377
913
 
914
+ #### 基础属性
915
+
378
916
  | 属性 | 类型 | 默认值 | 说明 |
379
917
  |------|------|--------|------|
380
918
  | `value` | `Value` | - | 编辑器内容 |
381
919
  | `onChange` | `(value: Value) => void` | - | 内容变化回调 |
382
920
  | `mode` | `'edit' \| 'view' \| 'suggestion'` | `'edit'` | 编辑器模式 |
921
+ | `disabled` | `boolean` | `false` | 是否禁用 |
922
+ | `readOnly` | `boolean` | `false` | 是否只读 |
923
+ | `autoFocus` | `boolean` | `false` | 是否自动聚焦 |
924
+ | `className` | `string` | - | 自定义类名 |
925
+
926
+ #### 工具栏属性
927
+
928
+ | 属性 | 类型 | 默认值 | 说明 |
929
+ |------|------|--------|------|
383
930
  | `toolbarConfig` | `ToolbarConfig` | `FULL_TOOLBAR` | 工具栏配置 |
384
931
  | `showToolbar` | `boolean` | `true` | 是否显示工具栏 |
932
+ | `toolbarSticky` | `boolean` | `true` | 工具栏是否吸顶 |
385
933
  | `toolbarAlign` | `'left' \| 'center' \| 'right'` | `'left'` | 工具栏对齐 |
386
934
  | `toolbarFullWidth` | `boolean` | `false` | 工具栏是否全宽 |
935
+ | `toolbarClassName` | `string` | - | 工具栏类名 |
936
+ | `toolbarStyle` | `CSSProperties` | - | 工具栏样式 |
937
+ | `customToolbarButtons` | `CustomToolbarButtons` | - | 自定义工具栏按钮 |
938
+
939
+ #### 目录属性
940
+
941
+ | 属性 | 类型 | 默认值 | 说明 |
942
+ |------|------|--------|------|
387
943
  | `showToc` | `boolean` | `false` | 是否显示目录 |
388
- | `tocPosition` | `'left' \| 'right'` | `'left'` | 目录位置 |
389
- | `autoFocus` | `boolean` | `false` | 是否自动聚焦 |
390
- | `placeholder` | `string` | - | 占位符文本 |
944
+ | `tocPosition` | `'left' \| 'right' \| 'top' \| 'custom'` | `'left'` | 目录位置 |
945
+ | `tocWidth` | `string \| number` | `'320px'` | 目录宽度 |
946
+ | `tocClassName` | `string` | - | 目录类名 |
947
+ | `tocStyle` | `CSSProperties` | - | 目录样式 |
948
+ | `renderToc` | `(toc: ReactNode) => ReactNode` | - | 自定义目录渲染 |
949
+
950
+ #### 保存属性 (v0.5.5+)
951
+
952
+ | 属性 | 类型 | 默认值 | 说明 |
953
+ |------|------|--------|------|
954
+ | `onSave` | `(content: Value) => void` | - | 快捷键保存回调 |
955
+ | `autoSave` | `boolean` | `false` | 是否启用自动保存 |
956
+ | `autoSaveKey` | `string` | - | localStorage 存储键名 |
957
+ | `autoSaveInterval` | `number` | `30000` | 自动保存间隔(毫秒) |
958
+ | `onAutoSave` | `(content: Value) => void` | - | 自动保存回调 |
959
+
960
+ #### 其他属性
961
+
962
+ | 属性 | 类型 | 默认值 | 说明 |
963
+ |------|------|--------|------|
964
+ | `showSettings` | `boolean` | `true` | 是否显示设置按钮 |
965
+ | `contentMaxWidth` | `string \| number` | - | 内容区域最大宽度 |
966
+ | `onModifiedChange` | `(isModified: boolean) => void` | - | 修改状态变化回调 |
391
967
 
392
968
  ---
393
969
 
@@ -2,6 +2,7 @@ import { Value } from 'platejs';
2
2
  import { TPlateEditor } from 'platejs/react';
3
3
  import { EditorPluginKit } from '../../types/plugin-types';
4
4
  import { ToolbarConfig, ToolbarAlign } from '../../types/toolbar-config';
5
+ import { HtmlSerializeOptions } from '../../lib/content-converter';
5
6
  import { EditorMode, WordCountResult, OutlineItem, FindOptions, ReplaceOptions, MatchPosition } from '../../types/editor-types';
6
7
  import * as React from 'react';
7
8
  /**
@@ -116,10 +117,25 @@ export interface PlateEditorRef {
116
117
  getMarkdown: () => string;
117
118
  /** 从 Markdown 加载内容 */
118
119
  setMarkdown: (markdown: string) => void;
119
- /** 导出为 HTML 文件 */
120
- getHtml: () => Promise<string>;
120
+ /**
121
+ * 导出为 HTML 格式
122
+ * @param options 序列化选项
123
+ * @returns HTML 字符串
124
+ */
125
+ getHtml: (options?: HtmlSerializeOptions) => Promise<string>;
121
126
  /** 从 HTML 加载内容 */
122
127
  setHtml: (html: string) => void;
128
+ /**
129
+ * 获取指定格式的内容
130
+ * @param format 内容格式:'json' | 'html' | 'markdown'
131
+ */
132
+ getContentAs: (format: 'json' | 'html' | 'markdown') => Promise<string | Value>;
133
+ /**
134
+ * 从指定格式加载内容
135
+ * @param content 内容字符串或 JSON
136
+ * @param format 内容格式:'json' | 'html' | 'markdown'
137
+ */
138
+ setContentFrom: (content: string | Value, format: 'json' | 'html' | 'markdown') => void;
123
139
  /** 获取纯文本内容 */
124
140
  getText: () => string;
125
141
  /** 检查编辑器是否为空 */
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const fl=require("./index-0mdn5jU9.js");/*! *****************************************************************************
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const fl=require("./index-ZtTcrgdr.js");/*! *****************************************************************************
2
2
  Copyright (c) Microsoft Corporation.
3
3
 
4
4
  Permission to use, copy, modify, and/or distribute this software for any
@@ -1,4 +1,4 @@
1
- import { g as Xu } from "./index-mh-7Yu-k.mjs";
1
+ import { g as Xu } from "./index-DbSGAc09.mjs";
2
2
  /*! *****************************************************************************
3
3
  Copyright (c) Microsoft Corporation.
4
4