@vervedoc/core 3.3.15 → 3.3.17

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
@@ -1,528 +1,181 @@
1
- # @wanghe1995/docx-editor-core
2
-
3
- DocxEditor 核心编辑器库,提供富文本编辑、表格、图片、列表等功能。
4
-
5
- ## 特性
6
-
7
- - 富文本编辑(加粗、斜体、下划线、删除线、高亮等)
8
- - 表格支持(插入、合并、拆分、边框设置等)
9
- - 图片处理(插入、缩放、拖拽、显示模式等)
10
- - 列表功能(有序列表、无序列表、多级列表)
11
- - 页面布局(页眉、页脚、页码、水印、页边距)
12
- - 控件系统(文本控件、日期控件、下拉选择等)
13
- - 历史记录(撤销/重做)
14
- - 搜索替换
15
- - 插件系统(支持扩展功能)
16
-
17
- ## 安装
18
-
19
- ```bash
20
- npm install @wanghe1995/docx-editor-core
21
- ```
22
-
23
- ## 快速开始
24
-
25
- ```typescript
26
- import DocxEditor from '@wanghe1995/docx-editor-core'
27
-
28
- // 获取容器元素
29
- const container = document.getElementById('editor') as HTMLDivElement
30
-
31
- // 初始化编辑器
32
- const editor = new DocxEditor(container, {
33
- main: [
34
- { value: '欢迎使用 DocxEditor!' }
35
- ]
36
- })
37
-
38
- // 使用命令 API
39
- editor.command.executeUndo() // 撤销
40
- editor.command.executeRedo() // 重做
41
- editor.command.executeSetBold() // 加粗
42
- ```
43
-
44
- ## 配置选项
45
-
46
- ```typescript
47
- interface IEditorOption {
48
- // 页面设置
49
- pageMode?: PageMode // 页面模式:paging(分页)| continuous(连续)
50
- paperDirection?: PaperDirection // 纸张方向:vertical(纵向)| horizontal(横向)
51
- width?: number // 页面宽度(毫米)
52
- height?: number // 页面高度(毫米)
53
- scale?: number // 缩放比例(0-1)
54
-
55
- // 边距设置
56
- margins?: [number, number, number, number] // [上, 右, 下, 左](毫米)
57
-
58
- // 页眉页脚
59
- header?: IHeader // 页眉配置
60
- footer?: IFooter // 页脚配置
61
-
62
- // 水印
63
- watermark?: IWatermark // 水印配置
64
-
65
- // 字体
66
- defaultFont?: string // 默认字体
67
- defaultSize?: number // 默认字号
68
-
69
- // 模式
70
- mode?: EditorMode // 编辑模式:edit | readonly | form | print
71
-
72
- // 其他
73
- placeholder?: IPlaceholder // 占位符配置
74
- pageNumber?: IPageNumber // 页码配置
75
- lineNumber?: ILineNumber // 行号配置
76
- }
77
- ```
78
-
79
- ## 数据结构
80
-
81
- ### IElement - 元素结构
82
-
83
- ```typescript
84
- interface IElement {
85
- // 基础属性
86
- id?: string // 元素 ID
87
- type?: ElementType // 元素类型
88
- value: string // 文本内容
89
-
90
- // 文本样式
91
- font?: string // 字体
92
- size?: number // 字号
93
- bold?: boolean // 加粗
94
- italic?: boolean // 斜体
95
- underline?: boolean // 下划线
96
- strikeout?: boolean // 删除线
97
- color?: string // 文字颜色
98
- highlight?: string // 高亮颜色
99
-
100
- // 段落样式
101
- rowFlex?: RowFlex // 对齐方式
102
- rowMargin?: number // 行距
103
-
104
- // 图片属性
105
- width?: number // 图片宽度
106
- height?: number // 图片高度
107
- imgDisplay?: ImageDisplay // 图片显示模式
108
-
109
- // 表格属性(type: 'table')
110
- trList?: ITr[] // 表格行列表
111
-
112
- // 列表属性
113
- listType?: ListType // 列表类型
114
- listStyle?: ListStyle // 列表样式
115
- listId?: string // 列表组 ID
116
-
117
- // 超链接
118
- url?: string // 链接地址
119
-
120
- // 控件属性
121
- control?: IControl // 控件配置
122
- }
123
- ```
124
-
125
- ### IEditorData - 编辑器数据
126
-
127
- ```typescript
128
- interface IEditorData {
129
- header?: IElement[] // 页眉元素
130
- main: IElement[] // 主体内容
131
- footer?: IElement[] // 页脚元素
132
- }
133
- ```
134
-
135
- ## 命令 API
136
-
137
- ### 编辑命令
138
-
139
- ```typescript
140
- // 撤销/重做
141
- editor.command.executeUndo()
142
- editor.command.executeRedo()
143
-
144
- // 剪切/复制/粘贴
145
- editor.command.executeCut()
146
- editor.command.executeCopy()
147
- editor.command.executePaste()
148
-
149
- // 全选/删除
150
- editor.command.executeSelectAll()
151
- editor.command.executeBackspace()
152
- ```
153
-
154
- ### 文本格式
155
-
156
- ```typescript
157
- // 字体样式
158
- editor.command.executeSetBold() // 加粗
159
- editor.command.executeSetItalic() // 斜体
160
- editor.command.executeSetUnderline() // 下划线
161
- editor.command.executeSetStrikeout() // 删除线
162
- editor.command.executeSetSuperscript() // 上标
163
- editor.command.executeSetSubscript() // 下标
164
-
165
- // 字体设置
166
- editor.command.executeSetFont('宋体') // 设置字体
167
- editor.command.executeSetSize(16) // 设置字号
168
- editor.command.executeSetColor('#ff0000') // 设置颜色
169
- editor.command.executeSetHighlight('#ffff00') // 设置高亮
170
- ```
171
-
172
- ### 段落格式
173
-
174
- ```typescript
175
- // 对齐方式
176
- editor.command.executeSetRowFlex(RowFlex.LEFT) // 左对齐
177
- editor.command.executeSetRowFlex(RowFlex.CENTER) // 居中
178
- editor.command.executeSetRowFlex(RowFlex.RIGHT) // 右对齐
179
- editor.command.executeSetRowFlex(RowFlex.JUSTIFY) // 两端对齐
180
-
181
- // 行距
182
- editor.command.executeSetRowMargin(1.5) // 设置行距
183
-
184
- // 标题
185
- editor.command.executeSetTitle(TitleLevel.FIRST) // 一级标题
186
- editor.command.executeSetTitle(TitleLevel.SECOND) // 二级标题
187
- editor.command.executeSetTitle(null) // 取消标题
188
- ```
189
-
190
- ### 列表
191
-
192
- ```typescript
193
- // 有序列表
194
- editor.command.executeSetList(ListType.OL, ListStyle.DECIMAL)
195
-
196
- // 无序列表
197
- editor.command.executeSetList(ListType.UL, ListStyle.DISC)
198
-
199
- // 取消列表
200
- editor.command.executeSetList(null, null)
201
- ```
202
-
203
- ### 插入内容
204
-
205
- ```typescript
206
- // 插入文本
207
- editor.command.executeInsertElementList([
208
- { value: '插入的文本' }
209
- ])
210
-
211
- // 插入图片
212
- editor.command.executeInsertImage({
213
- value: 'base64...', // 或图片 URL
214
- width: 200,
215
- height: 150
216
- })
217
-
218
- // 插入表格
219
- editor.command.executeInsertTable(3, 4) // 3行4列
220
-
221
- // 插入分页符
222
- editor.command.executePageBreak()
223
-
224
- // 插入水印
225
- editor.command.executeAddWatermark({
226
- data: '机密文件',
227
- color: '#cccccc',
228
- size: 60
229
- })
230
- ```
231
-
232
- ### 表格操作
233
-
234
- ```typescript
235
- // 插入行/列
236
- editor.command.executeInsertTableRow('above') // 上方插入行
237
- editor.command.executeInsertTableRow('below') // 下方插入行
238
- editor.command.executeInsertTableCol('left') // 左侧插入列
239
- editor.command.executeInsertTableCol('right') // 右侧插入列
240
-
241
- // 删除行/列
242
- editor.command.executeDeleteTableRow() // 删除行
243
- editor.command.executeDeleteTableCol() // 删除列
244
-
245
- // 合并单元格
246
- editor.command.executeMergeTableCells() // 合并选中单元格
247
-
248
- // 表格边框
249
- editor.command.executeSetTableBorderType(TableBorder.ALL) // 所有边框
250
- editor.command.executeSetTableBorderType(TableBorder.NONE) // 无边框
251
- editor.command.executeSetTableBorderType(TableBorder.OUTSIDE) // 外边框
252
- ```
253
-
254
- ### 搜索替换
255
-
256
- ```typescript
257
- // 搜索
258
- const result = editor.command.executeSearch('关键词')
259
-
260
- // 替换
261
- editor.command.executeReplace('新文本')
262
-
263
- // 全部替换
264
- editor.command.executeReplaceAll('旧文本', '新文本')
265
- ```
266
-
267
- ### 获取数据
268
-
269
- ```typescript
270
- // 获取编辑器数据
271
- const data = editor.command.getValue()
272
-
273
- // 获取字数统计
274
- const wordCount = editor.command.getWordCount()
275
-
276
- // 获取页面缩略图
277
- const images = editor.command.getPageThumbnails()
278
- ```
279
-
280
- ## 事件监听
281
-
282
- 编辑器通过 `listener` 提供分组事件订阅 API,每个分组返回取消订阅函数。所有事件名使用 camelCase,命名空间方法不带 on 前缀、不带 Change 后缀,以 Listener 结尾。
283
-
284
- ### 内容事件
285
-
286
- ```typescript
287
- // 内容变更(文本增删/格式修改等)
288
- const off = editor.listener.content.contentListener(() => {
289
- console.log('内容已变化')
290
- })
291
-
292
- // 文档保存完成
293
- editor.listener.content.savedListener(() => {
294
- console.log('已保存')
295
- })
296
-
297
- // 取消订阅
298
- off()
299
- ```
300
-
301
- ### 选区事件
302
-
303
- ```typescript
304
- // 选区变更(光标移动/选区改变)
305
- editor.listener.range.rangeListener((range) => {
306
- console.log('当前选区:', range)
307
- })
308
-
309
- // 格式变更(bold/italic 等回显状态)
310
- editor.listener.range.formatListener((style) => {
311
- console.log('当前样式:', style)
312
- })
313
-
314
- // 光标位置变更
315
- editor.listener.range.positionListener((pos) => {
316
- console.log('光标位置:', pos)
317
- })
318
- ```
319
-
320
- ### 页面事件
321
-
322
- ```typescript
323
- // 缩放比例变更
324
- editor.listener.page.pageScaleListener((scale) => {
325
- console.log('缩放比例:', scale)
326
- })
327
-
328
- // 页面尺寸变更(宽高)
329
- editor.listener.page.pageSizeListener((size) => {
330
- console.log('页面尺寸:', size)
331
- })
332
-
333
- // 总页数变更
334
- editor.listener.page.pageCountListener((count) => {
335
- console.log('总页数:', count)
336
- })
337
-
338
- // 当前页码变更
339
- editor.listener.page.currentPageNoListener((pageNo) => {
340
- console.log('当前页码:', pageNo)
341
- })
342
- ```
343
-
344
- ### 目录事件
345
-
346
- ```typescript
347
- // 目录变更(由核心 Worker 后台计算后自动推送)
348
- editor.listener.toc.tocListener((toc) => {
349
- console.log('目录已更新:', toc)
350
- })
351
- ```
352
-
353
- ### 缩略图事件
354
-
355
- ```typescript
356
- // 缩略图变更(由核心 afterRender 自动生成并推送)
357
- editor.listener.thumbnail.thumbnailListener((images) => {
358
- console.log('缩略图数量:', images.length)
359
- })
360
- ```
361
-
362
- ### 能力事件
363
-
364
- ```typescript
365
- // 编辑器能力变更(readonly/disabled/canUndo/canRedo)
366
- editor.listener.ability.abilityListener((ability) => {
367
- console.log('编辑器能力:', ability)
368
- })
369
- ```
370
-
371
- ### 区域事件
372
-
373
- ```typescript
374
- // 编辑区域切换(正文/页眉/页脚)
375
- editor.listener.zone.zoneListener((zone) => {
376
- console.log('当前区域:', zone) // 'main' | 'header' | 'footer'
377
- })
378
- ```
379
-
380
- ### 生命周期事件
381
-
382
- ```typescript
383
- // 编辑器获得焦点
384
- editor.listener.lifecycle.focusListener(() => {
385
- console.log('获得焦点')
386
- })
387
-
388
- // 编辑器失去焦点
389
- editor.listener.lifecycle.blurListener(() => {
390
- console.log('失去焦点')
391
- })
392
- ```
393
-
394
- ### 请求事件
395
-
396
- ```typescript
397
- // 请求插入图片(右键菜单触发)
398
- editor.listener.request.requestInsertImageListener(() => {
399
- console.log('请求插入图片')
400
- })
401
-
402
- // 请求插入超链接
403
- editor.listener.request.requestInsertHyperlinkListener(() => {
404
- console.log('请求插入超链接')
405
- })
406
-
407
- // 请求插入公式
408
- editor.listener.request.requestInsertFormulaListener(() => {
409
- console.log('请求插入公式')
410
- })
411
- ```
412
-
413
- ### 底层事件 API
414
-
415
- ```typescript
416
- // 直接通过事件名订阅(camelCase)
417
- const off = editor.listener.on('contentChange', () => {
418
- console.log('内容已变化')
419
- })
420
-
421
- // 取消订阅
422
- editor.listener.off('contentChange', handler)
423
-
424
- // 所有可用事件名:
425
- // 'contentChange' | 'saved' | 'rangeChange' | 'formatChange' | 'positionChange'
426
- // 'pageScaleChange' | 'pageSizeChange' | 'pageCountChange' | 'currentPageNoChange'
427
- // 'tocChange' | 'thumbnailChange' | 'abilityChange' | 'zoneChange'
428
- // 'focus' | 'blur' | 'requestInsertImage' | 'requestInsertHyperlink' | 'requestInsertFormula'
429
- ```
430
-
431
- ## 插件系统
432
-
433
- ### 使用插件
434
-
435
- ```typescript
436
- // 使用图表插件(需要额外安装 @docuflow/docx-editor-chart)
437
- import { createChartPlugin } from '@docuflow/docx-editor-chart'
438
- import * as echarts from 'echarts'
439
-
440
- editor.use(createChartPlugin({ echarts }))
441
- ```
442
-
443
- ### 自定义右键菜单
444
-
445
- ```typescript
446
- editor.register.registerContextMenuList([
447
- {
448
- key: 'myMenu',
449
- name: '自定义菜单',
450
- when: (context) => true, // 显示条件
451
- callback: (command, context) => {
452
- console.log('点击了自定义菜单')
453
- }
454
- }
455
- ])
456
- ```
457
-
458
- ### 自定义快捷键
459
-
460
- ```typescript
461
- editor.register.registerShortcutList([
462
- {
463
- key: 'mod+shift+c',
464
- callback: (command) => {
465
- command.executeCopy()
466
- }
467
- }
468
- ])
469
- ```
470
-
471
- ## 销毁
472
-
473
- ```typescript
474
- // 销毁编辑器实例
475
- editor.destroy()
476
- ```
477
-
478
- ## 类型导出
479
-
480
- ```typescript
481
- import {
482
- // 编辑器类
483
- DocxEditor,
484
- Editor, // DocxEditor 别名
485
- Command,
486
-
487
- // 枚举
488
- RowFlex,
489
- VerticalAlign,
490
- EditorZone,
491
- EditorMode,
492
- ElementType,
493
- ControlType,
494
- PageMode,
495
- ImageDisplay,
496
- KeyMap,
497
- BlockType,
498
- PaperDirection,
499
- TableBorder,
500
- TitleLevel,
501
- ListType,
502
- ListStyle,
503
-
504
- // 类型
505
- IElement,
506
- IEditorData,
507
- IEditorOption,
508
- IEditorResult,
509
- IWatermark,
510
- IRange,
511
-
512
- // 工具函数
513
- splitText,
514
- getElementListByHTML,
515
- getTextFromElementList
516
- } from '@docuflow/docx-editor-core'
517
- ```
518
-
519
- ## 浏览器兼容性
520
-
521
- - Chrome 80+
522
- - Firefox 75+
523
- - Safari 13.1+
524
- - Edge 80+
525
-
526
- ## License
527
-
528
- MIT
1
+ <div align="center">
2
+
3
+ <h1>玉衡云文档 · Core</h1>
4
+
5
+ <p><code>@vervedoc/core</code></p>
6
+
7
+ <p>
8
+ <a href="https://www.npmjs.com/package/@vervedoc/core"><img src="https://img.shields.io/npm/v/%40vervedoc%2Fcore?label=npm" alt="npm version"></a>
9
+ <a href="https://www.npmjs.com/package/@vervedoc/core"><img src="https://img.shields.io/npm/l/%40vervedoc%2Fcore" alt="license"></a>
10
+ <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-%3E%3D16-339933?logo=nodedotjs&logoColor=white" alt="Node.js version"></a>
11
+ </p>
12
+
13
+ <p>Canvas 文档编辑引擎 · 文档模型、排版与交互</p>
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ `@vervedoc/core` 是玉衡云文档的编辑器核心,负责文档树管理、排版布局、Canvas 绘制、选区与命令分发、历史记录、快捷键、目录及搜索。它不包含完整工具栏 UI,也不负责 DOCX 文件转换或远端存储。
20
+
21
+ <p align="center">
22
+ <a href="#快速开始">快速开始</a> ·
23
+ <a href="#文档模型">文档模型</a> ·
24
+ <a href="#命令与状态">命令与状态</a> ·
25
+ <a href="#插件">插件</a> ·
26
+ <a href="#选项">选项</a> ·
27
+ <a href="#包结构">包结构</a>
28
+ </p>
29
+
30
+ 如果需要带工具栏和对话框的完整 Vue 编辑器,请使用 [`@vervedoc/docx`](../docx/README.md)。直接使用本包适合需要自行构建界面或集成核心编辑能力的项目。
31
+
32
+ ## 安装
33
+
34
+ ```bash
35
+ pnpm add @vervedoc/core
36
+ ```
37
+
38
+ ## 快速开始
39
+
40
+ ```ts
41
+ import DocxEditor from '@vervedoc/core'
42
+
43
+ const container = document.querySelector<HTMLDivElement>('#editor')
44
+ if (!container) throw new Error('找不到编辑器容器')
45
+
46
+ const editor = new DocxEditor(
47
+ container,
48
+ {
49
+ success: true,
50
+ elements: [
51
+ {
52
+ type: 'title',
53
+ value: '',
54
+ level: 'first',
55
+ valueList: [{ type: 'text', value: '示例文档' }]
56
+ },
57
+ { type: 'text', value: '这是使用 VerveDocs Core 创建的文档。' }
58
+ ]
59
+ },
60
+ {
61
+ pageMode: 'paging',
62
+ defaultFont: '宋体',
63
+ defaultSize: 12
64
+ }
65
+ )
66
+
67
+ editor.command.executeInsertText('继续输入内容')
68
+ editor.command.executeSetBold()
69
+
70
+ // 页面卸载时释放 Canvas、Worker、事件和插件资源
71
+ editor.destroy()
72
+ ```
73
+
74
+ 构造函数签名为 `new DocxEditor(container, document, options?)`。`container` 必须是 `HTMLDivElement`;文档必须是 `IDocxDocumentMeta`,至少提供 `elements` 数组。旧版的 `IElement[]` 或 `{ main: [...] }` 文档形态不再作为构造参数接受。
75
+
76
+ ## 文档模型
77
+
78
+ `IDocxDocumentMeta` 表示完整文档元数据,正文放在 `elements` 中。模型还可包含页眉页脚、分节、样式表、编号、主题、批注和书签等数据。
79
+
80
+ ```ts
81
+ import type { IDocxDocumentMeta, IElement } from '@vervedoc/core'
82
+
83
+ const paragraph: IElement = {
84
+ type: 'text',
85
+ value: '正文文本',
86
+ bold: true,
87
+ size: 12
88
+ }
89
+
90
+ const document: IDocxDocumentMeta = {
91
+ success: true,
92
+ elements: [paragraph],
93
+ meta: { title: '设计说明', author: '作者' }
94
+ }
95
+ ```
96
+
97
+ 元素和样式的完整定义由 `@vervedoc/docx-editor-schema` 提供,并从 `@vervedoc/core` 透出。
98
+
99
+ ## 命令与状态
100
+
101
+ 常用操作通过 `editor.command` 执行:
102
+
103
+ ```ts
104
+ editor.command.executeSetBold()
105
+ editor.command.executeSetFont('宋体')
106
+ editor.command.executeSetSize(14)
107
+ editor.command.executeInsertText('新增文本')
108
+ editor.command.executeUndo()
109
+ editor.command.executeRedo()
110
+
111
+ const documentState = editor.getDocument()
112
+ ```
113
+
114
+ `command` 提供编辑、格式、表格、页面、书签等命令;`listener` 用于订阅内容、选区、页面、能力和生命周期变化;`eventBus` 用于编辑器交互事件;`range` 暴露选区管理能力。命令与事件的完整类型可从包入口和 schema 类型中查询。
115
+
116
+ ## 插件
117
+
118
+ 核心通过 `EditorPlugin` 契约接收可选插件。插件在 `editor.use()` 时安装,编辑器销毁时会调用插件的 `destroy()`。
119
+
120
+ ```ts
121
+ import DocxEditor from '@vervedoc/core'
122
+ import { createCommentPlugin } from '@vervedoc/docx-editor-comment'
123
+
124
+ const editor = new DocxEditor(container, {
125
+ success: true,
126
+ elements: []
127
+ })
128
+
129
+ const comments = createCommentPlugin()
130
+ editor.use(comments)
131
+
132
+ // 批注插件提供的扩展 API
133
+ comments.add('当前用户')
134
+ console.log(comments.getAll())
135
+ ```
136
+
137
+ `editor.getPlugin(name)` 可获取已注册插件。可选插件包括批注/修订和图表等;各插件包的安装方式及依赖请查看对应 README。AI 与协作扩展有各自的配置和生命周期 API,不应假定它们都使用相同的插件对象接口。
138
+
139
+ ## 导入与导出
140
+
141
+ Core 只定义文档模型,不内置 DOCX 解析器或生成器。`DocxImportCallback`、`DocxExportCallback` 是供宿主层使用的类型;可以使用 `@vervedoc/docx-parser`、服务端转换服务或自定义实现。
142
+
143
+ ## 选项
144
+
145
+ `IEditorOption` 常用字段包括:
146
+
147
+ - `readonly`、`disabled`:限制编辑能力。
148
+ - `pageMode`:`paging` 分页或 `continuity` 连续布局。
149
+ - `pageWidth`、`pageHeight`、`pageMargins`、`scale`:页面尺寸与显示设置。
150
+ - `defaultFont`、`defaultSize`、`defaultLineHeight`:默认排版设置。
151
+ - `trackChanges`、`revisionAuthor`:修订记录相关设置。
152
+ - `locale`:编辑器语言。
153
+
154
+ 页面单位及其他详细选项以导出的 `IEditorOption` 类型为准。
155
+
156
+ ## 包结构
157
+
158
+ 独立子包用于拆分编辑器内部职责,也可以在高级集成中单独使用:
159
+
160
+ | 包 | 职责 |
161
+ | --- | --- |
162
+ | `@vervedoc/docx-editor-schema` | 文档树、类型、常量和纯数据工具 |
163
+ | `@vervedoc/docx-editor-state` | 事件总线、监听器和选区状态 |
164
+ | `@vervedoc/docx-editor-transform` | 命令门面与文档变换 |
165
+ | `@vervedoc/docx-editor-view` | 布局、Canvas 绘制和命中测试 |
166
+ | `@vervedoc/docx-editor-commands` | 搜索、控件、日期、公式和块级命令组件 |
167
+ | `@vervedoc/docx-editor-history` | 快照历史管理 |
168
+ | `@vervedoc/docx-editor-keymap` | 键盘快捷键处理 |
169
+
170
+ 大多数应用应直接依赖 `@vervedoc/core`,避免自行组装底层模块造成版本或生命周期不一致。
171
+
172
+ ## 开发
173
+
174
+ ```bash
175
+ pnpm --filter @vervedoc/core type:check
176
+ pnpm --filter @vervedoc/core build
177
+ ```
178
+
179
+ ## 许可
180
+
181
+ MIT