@kaitify/core 0.0.3-beta.1 → 0.0.3-beta.3
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 +492 -2
- package/lib/extensions/Extension.d.ts +4 -4
- package/lib/extensions/code-block/index.d.ts +1 -1
- package/lib/extensions/link/index.d.ts +1 -1
- package/lib/kaitify-core.es.js +2604 -1980
- package/lib/kaitify-core.umd.js +2 -2
- package/lib/model/Editor.d.ts +5 -6
- package/lib/model/KNode.d.ts +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,3 +1,493 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# @kaitify/core
|
|
4
|
+
|
|
5
|
+
**基于原生 JavaScript 构建的富文本编辑器核心库**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@kaitify/core)
|
|
8
|
+
[](https://github.com/so-better/kaitify-core/blob/main/LICENSE)
|
|
9
|
+
[](https://www.npmjs.com/package/@kaitify/core)
|
|
10
|
+
|
|
11
|
+
[官方文档](https://www.so-better.cn/docs/kaitify-core/) · [GitHub](https://github.com/so-better/kaitify-core) · [更新日志](./docs/changelog.md)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 简介
|
|
18
|
+
|
|
19
|
+
`kaitify`(发音:/ˈkeɪtɪfaɪ/)是一款**无 UI** 的富文本编辑器核心库。它不提供开箱即用的编辑器界面,而是提供构建编辑器所需的底层 API 和配置,让开发者在此之上灵活封装,满足高度定制化的需求。
|
|
20
|
+
|
|
21
|
+
- **框架无关**:不依赖 React、Vue 等任何前端框架,完全由原生 JavaScript 编写,可与任意技术栈整合
|
|
22
|
+
- **内置丰富扩展**:内置大量开箱即用的扩展(`Extension`),覆盖常见富文本功能,足以快速搭建功能完整的编辑器
|
|
23
|
+
- **高可扩展性**:提供完整的扩展机制,允许开发者自定义扩展实现任意功能
|
|
24
|
+
- **TypeScript 支持**:完整的类型定义,提供良好的开发体验
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 安装
|
|
29
|
+
|
|
30
|
+
### npm / yarn / pnpm
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# npm
|
|
34
|
+
npm install @kaitify/core
|
|
35
|
+
npm install @kaitify/core@0.0.3-beta.3
|
|
36
|
+
|
|
37
|
+
# yarn
|
|
38
|
+
yarn add @kaitify/core
|
|
39
|
+
yarn add @kaitify/core@0.0.3-beta.3
|
|
40
|
+
|
|
41
|
+
# pnpm
|
|
42
|
+
pnpm add @kaitify/core
|
|
43
|
+
pnpm add @kaitify/core@0.0.3-beta.3
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### CDN
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<!-- UMD 版本(全局变量方式) -->
|
|
50
|
+
<script src="https://unpkg.com/@kaitify/core/lib/kaitify-core.umd.js"></script>
|
|
51
|
+
|
|
52
|
+
<!-- ES Module 版本 -->
|
|
53
|
+
<script type="module">
|
|
54
|
+
import { Editor } from 'https://unpkg.com/@kaitify/core/lib/kaitify-core.es.js'
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 快速上手
|
|
61
|
+
|
|
62
|
+
### 构建一个编辑器
|
|
63
|
+
|
|
64
|
+
编辑器的创建和渲染是异步的,需要通过 `await` 等待实例返回。
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<div id="editor" style="width:500px;height:300px;"></div>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { Editor } from '@kaitify/core'
|
|
72
|
+
|
|
73
|
+
const editor = await Editor.configure({
|
|
74
|
+
el: '#editor',
|
|
75
|
+
value: '<p>hello kaitify</p>',
|
|
76
|
+
placeholder: '请输入正文...'
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 创建节点并更新编辑器
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { Editor, KNode } from '@kaitify/core'
|
|
84
|
+
|
|
85
|
+
const editor = await Editor.configure({
|
|
86
|
+
el: '#editor',
|
|
87
|
+
value: '<p>hello</p>'
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const paragraph = KNode.create({
|
|
91
|
+
type: 'block',
|
|
92
|
+
tag: 'p',
|
|
93
|
+
children: [{ type: 'text', textContent: '我是一个段落' }]
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// 直接赋值 stackNodes 会替换编辑器全部内容
|
|
97
|
+
editor.stackNodes = [paragraph]
|
|
98
|
+
// 调用 updateView 才会更新视图
|
|
99
|
+
editor.updateView()
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 监听编辑器事件
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
const editor = await Editor.configure({
|
|
106
|
+
el: '#editor',
|
|
107
|
+
value: '',
|
|
108
|
+
onChange(newVal, oldVal) {
|
|
109
|
+
console.log('内容变化:', newVal)
|
|
110
|
+
},
|
|
111
|
+
onSelectionUpdate(selection) {
|
|
112
|
+
console.log('光标变化:', selection)
|
|
113
|
+
},
|
|
114
|
+
onFocus(event) {
|
|
115
|
+
console.log('编辑器聚焦')
|
|
116
|
+
},
|
|
117
|
+
onBlur(event) {
|
|
118
|
+
console.log('编辑器失焦')
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 核心概念
|
|
126
|
+
|
|
127
|
+
### Editor
|
|
128
|
+
|
|
129
|
+
`Editor` 是 kaitify 最核心的对象,通过静态方法 `Editor.configure` 创建编辑器实例。
|
|
130
|
+
|
|
131
|
+
**构建参数(部分常用):**
|
|
132
|
+
|
|
133
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
134
|
+
|------|------|--------|------|
|
|
135
|
+
| `el` | `HTMLElement \| string` | — | 编辑器挂载的 DOM 或选择器 |
|
|
136
|
+
| `value` | `string` | — | 初始 HTML 内容 |
|
|
137
|
+
| `editable` | `boolean` | `true` | 是否可编辑 |
|
|
138
|
+
| `autofocus` | `boolean` | `false` | 是否自动聚焦 |
|
|
139
|
+
| `placeholder` | `string` | — | 占位文字 |
|
|
140
|
+
| `dark` | `boolean` | `false` | 深色模式 |
|
|
141
|
+
| `allowCopy` | `boolean` | `true` | 是否允许复制 |
|
|
142
|
+
| `allowPaste` | `boolean` | `true` | 是否允许粘贴 |
|
|
143
|
+
| `allowCut` | `boolean` | `true` | 是否允许剪切 |
|
|
144
|
+
| `allowPasteHtml` | `boolean` | `false` | 粘贴时是否保留样式 |
|
|
145
|
+
| `priorityPasteFiles` | `boolean` | `false` | 剪贴板同时有文件和文本时是否优先粘贴文件 |
|
|
146
|
+
| `textRenderTag` | `string` | `"span"` | 文本节点渲染标签 |
|
|
147
|
+
| `blockRenderTag` | `string` | `"p"` | 默认块级节点渲染标签 |
|
|
148
|
+
| `emptyRenderTags` | `string[]` | — | 需要置空的标签 |
|
|
149
|
+
| `extraKeepTags` | `string[]` | — | 额外保留的标签 |
|
|
150
|
+
| `extensions` | `Extension[]` | — | 扩展数组 |
|
|
151
|
+
| `formatRules` | `RuleFunctionType[]` | — | 自定义格式化规则 |
|
|
152
|
+
|
|
153
|
+
**事件回调(部分常用):**
|
|
154
|
+
|
|
155
|
+
| 参数 | 说明 |
|
|
156
|
+
|------|------|
|
|
157
|
+
| `onChange` | 内容改变时触发,参数为新值和旧值 |
|
|
158
|
+
| `onSelectionUpdate` | 光标变化时触发 |
|
|
159
|
+
| `onFocus` | 编辑器聚焦时触发 |
|
|
160
|
+
| `onBlur` | 编辑器失焦时触发 |
|
|
161
|
+
| `onKeydown` | 键盘按下时触发 |
|
|
162
|
+
| `onKeyup` | 键盘松开时触发 |
|
|
163
|
+
| `onInsertParagraph` | 换行时触发,参数为换行后光标所在块节点 |
|
|
164
|
+
| `onDeleteComplete` | 删除完成时触发 |
|
|
165
|
+
| `onPasteText` | 粘贴纯文本时触发,返回 `false` 可阻止默认行为 |
|
|
166
|
+
| `onPasteHtml` | 粘贴 HTML 时触发,返回 `false` 可阻止默认行为 |
|
|
167
|
+
| `onPasteImage` | 粘贴图片时触发,返回 `false` 可阻止默认行为 |
|
|
168
|
+
| `onPasteVideo` | 粘贴视频时触发,返回 `false` 可阻止默认行为 |
|
|
169
|
+
| `onPasteFile` | 粘贴其他文件时触发 |
|
|
170
|
+
| `onPasteKeepMarks` | 粘贴 HTML 时自定义保留节点标记 |
|
|
171
|
+
| `onPasteKeepStyles` | 粘贴 HTML 时自定义保留节点样式 |
|
|
172
|
+
| `onCreate` | 编辑器创建时触发 |
|
|
173
|
+
| `onCreated` | 编辑器创建完成后触发 |
|
|
174
|
+
| `onBeforeUpdateView` | 视图更新前触发 |
|
|
175
|
+
| `onAfterUpdateView` | 视图更新后触发 |
|
|
176
|
+
| `onUpdateView` | 视图渲染时触发,返回 `false` 可自定义渲染逻辑 |
|
|
177
|
+
| `onDomParseNode` | DOM 转节点时的后置处理 |
|
|
178
|
+
| `onRedressSelection` | 光标纠正时触发 |
|
|
179
|
+
| `onDetachMentBlockFromParent` | 块节点从父节点抽离时触发,返回 `false` 可自定义处理 |
|
|
180
|
+
| `onBeforePatchNodeToFormat` | 节点被格式化前触发 |
|
|
181
|
+
|
|
182
|
+
**常用实例方法:**
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
// 获取编辑器 HTML 内容
|
|
186
|
+
editor.getHTML()
|
|
187
|
+
|
|
188
|
+
// 获取编辑器纯文本内容
|
|
189
|
+
editor.getContent()
|
|
190
|
+
|
|
191
|
+
// 判断编辑器内容是否为空
|
|
192
|
+
editor.isEmpty()
|
|
193
|
+
|
|
194
|
+
// 向选区插入文本
|
|
195
|
+
editor.insertText('hello')
|
|
196
|
+
|
|
197
|
+
// 向选区插入节点
|
|
198
|
+
editor.insertNode(node)
|
|
199
|
+
|
|
200
|
+
// 向选区进行换行
|
|
201
|
+
editor.insertParagraph()
|
|
202
|
+
|
|
203
|
+
// 对选区进行删除
|
|
204
|
+
editor.delete()
|
|
205
|
+
|
|
206
|
+
// 更新编辑器视图
|
|
207
|
+
await editor.updateView()
|
|
208
|
+
|
|
209
|
+
// 重新渲染编辑器视图
|
|
210
|
+
await editor.review('<p>new content</p>')
|
|
211
|
+
|
|
212
|
+
// 设置是否可编辑
|
|
213
|
+
editor.setEditable(false)
|
|
214
|
+
|
|
215
|
+
// 设置深色模式
|
|
216
|
+
editor.setDark(true)
|
|
217
|
+
|
|
218
|
+
// 销毁编辑器
|
|
219
|
+
editor.destroy()
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### KNode
|
|
223
|
+
|
|
224
|
+
`KNode` 是编辑器内容的基础数据类型,编辑器内所有 HTML 内容都被表示为节点树,挂载在 `editor.stackNodes` 下。
|
|
225
|
+
|
|
226
|
+
**节点类型:**
|
|
227
|
+
|
|
228
|
+
| 类型 | 说明 |
|
|
229
|
+
|------|------|
|
|
230
|
+
| `block` | 块节点,`stackNodes` 中的顶层节点均为块节点 |
|
|
231
|
+
| `inline` | 行内节点,必须包含子节点,子节点可以是 `text`、`closed`、`inline` |
|
|
232
|
+
| `closed` | 闭合节点,无子节点,对应的真实 DOM 内部视为黑盒,如图片、视频等 |
|
|
233
|
+
| `text` | 文本节点,存储文本内容,无 `tag`,无子节点 |
|
|
234
|
+
|
|
235
|
+
**创建节点:**
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
// 创建普通节点
|
|
239
|
+
const node = KNode.create({
|
|
240
|
+
type: 'block',
|
|
241
|
+
tag: 'p',
|
|
242
|
+
children: [{ type: 'text', textContent: '这是一段文字' }]
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
// 创建零宽度空白文本节点
|
|
246
|
+
const zeroNode = KNode.createZeroWidthText()
|
|
247
|
+
|
|
248
|
+
// 创建占位符节点(<br />)
|
|
249
|
+
const placeholder = KNode.createPlaceholder()
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**常用实例方法:**
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
node.isBlock() // 是否块节点
|
|
256
|
+
node.isInline() // 是否行内节点
|
|
257
|
+
node.isClosed() // 是否闭合节点
|
|
258
|
+
node.isText() // 是否文本节点
|
|
259
|
+
node.isEmpty() // 是否空节点
|
|
260
|
+
node.isPlaceholder() // 是否占位符节点
|
|
261
|
+
node.isZeroWidthText() // 是否零宽度空白文本节点
|
|
262
|
+
node.hasMarks() // 是否含有标记
|
|
263
|
+
node.hasStyles() // 是否含有样式
|
|
264
|
+
node.getBlock() // 获取所在块级节点
|
|
265
|
+
node.getRootBlock() // 获取所在根级块节点
|
|
266
|
+
node.getInline() // 获取所在行内节点
|
|
267
|
+
node.clone() // 复制节点
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 内置扩展
|
|
273
|
+
|
|
274
|
+
kaitify 内置了覆盖常见场景的扩展,无需额外配置即可使用,通过 `editor.commands` 调用扩展提供的命令。
|
|
275
|
+
|
|
276
|
+
**文本格式:**
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
editor.commands.setBold() // 设置加粗
|
|
280
|
+
editor.commands.unsetBold() // 取消加粗
|
|
281
|
+
editor.commands.isBold() // 是否加粗
|
|
282
|
+
|
|
283
|
+
editor.commands.setItalic() // 设置斜体
|
|
284
|
+
editor.commands.setUnderline() // 设置下划线
|
|
285
|
+
editor.commands.setStrikethrough() // 设置删除线
|
|
286
|
+
editor.commands.setSuperscript() // 设置上标
|
|
287
|
+
editor.commands.setSubscript() // 设置下标
|
|
288
|
+
editor.commands.setCode() // 设置行内代码
|
|
289
|
+
editor.commands.unsetCode() // 取消行内代码
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**字体与颜色:**
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
editor.commands.setFontSize('18px') // 设置字号
|
|
296
|
+
editor.commands.setFontFamily('Arial') // 设置字体
|
|
297
|
+
editor.commands.setColor('#ff0000') // 设置文字颜色
|
|
298
|
+
editor.commands.setBackColor('#ffff00') // 设置背景颜色
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**段落与对齐:**
|
|
302
|
+
|
|
303
|
+
```ts
|
|
304
|
+
// level: 0 表示普通段落,1~6 对应 h1~h6
|
|
305
|
+
editor.commands.setHeading(1) // 设置一级标题
|
|
306
|
+
editor.commands.unsetHeading(1) // 取消一级标题
|
|
307
|
+
editor.commands.setAlign('center') // 设置对齐:left / center / right / justify
|
|
308
|
+
editor.commands.setLineHeight(1.8) // 设置行高
|
|
309
|
+
editor.commands.setIncreaseIndent() // 增加缩进
|
|
310
|
+
editor.commands.setDecreaseIndent() // 减少缩进
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**列表与引用:**
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
editor.commands.setList({ ordered: true }) // 设置有序列表
|
|
317
|
+
editor.commands.setList({ ordered: false }) // 设置无序列表
|
|
318
|
+
editor.commands.unsetList({ ordered: true }) // 取消有序列表
|
|
319
|
+
editor.commands.setBlockquote() // 设置引用块
|
|
320
|
+
editor.commands.unsetBlockquote() // 取消引用块
|
|
321
|
+
editor.commands.setTask() // 设置待办列表
|
|
322
|
+
editor.commands.unsetTask() // 取消待办列表
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**媒体与嵌入:**
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
// 插入图片
|
|
329
|
+
editor.commands.setImage({ src: 'https://example.com/image.jpg', alt: '图片描述', width: '100%' })
|
|
330
|
+
|
|
331
|
+
// 插入视频
|
|
332
|
+
editor.commands.setVideo({ src: 'https://example.com/video.mp4', autoplay: false })
|
|
333
|
+
|
|
334
|
+
// 插入超链接(光标折叠时需提供 text;有选区时以选区内容作为链接文字)
|
|
335
|
+
editor.commands.setLink({ href: 'https://example.com', text: '链接文字', newOpen: true })
|
|
336
|
+
|
|
337
|
+
// 插入水平分割线
|
|
338
|
+
editor.commands.setHorizontal()
|
|
339
|
+
|
|
340
|
+
// 插入数学公式(KaTeX 语法)
|
|
341
|
+
editor.commands.setMath('x^2 + y^2 = z^2')
|
|
342
|
+
|
|
343
|
+
// 插入代码块
|
|
344
|
+
editor.commands.setCodeBlock()
|
|
345
|
+
|
|
346
|
+
// 插入表格(3 行 4 列)
|
|
347
|
+
editor.commands.setTable({ rows: 3, columns: 4 })
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**历史记录:**
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
editor.commands.undo() // 撤销
|
|
354
|
+
editor.commands.redo() // 重做
|
|
355
|
+
editor.commands.canUndo() // 是否可撤销
|
|
356
|
+
editor.commands.canRedo() // 是否可重做
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**使用需要配置参数的扩展:**
|
|
360
|
+
|
|
361
|
+
部分扩展支持通过入参进行配置,需将扩展函数调用结果传入 `extensions`:
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
import { Editor, AttachmentExtension, CodeBlockExtension } from '@kaitify/core'
|
|
365
|
+
|
|
366
|
+
const editor = await Editor.configure({
|
|
367
|
+
el: '#editor',
|
|
368
|
+
value: '',
|
|
369
|
+
extensions: [
|
|
370
|
+
AttachmentExtension({ icon: 'path/to/icon.png' }),
|
|
371
|
+
CodeBlockExtension({
|
|
372
|
+
handleCopy: (code) => {
|
|
373
|
+
// 自定义点击复制的逻辑
|
|
374
|
+
}
|
|
375
|
+
})
|
|
376
|
+
]
|
|
377
|
+
})
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 自定义扩展
|
|
383
|
+
|
|
384
|
+
通过 `Extension.create` 创建自定义扩展,将格式化规则、事件回调和命令集中管理:
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
import { Editor, Extension } from '@kaitify/core'
|
|
388
|
+
|
|
389
|
+
const myExtension = Extension.create({
|
|
390
|
+
name: 'myExtension',
|
|
391
|
+
// 自定义格式化规则
|
|
392
|
+
formatRules: [
|
|
393
|
+
({ editor, node }) => {
|
|
394
|
+
if (node.isBlock() && node.tag === editor.blockRenderTag) {
|
|
395
|
+
node.styles = { ...node.styles, color: 'red' }
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
// 自定义命令
|
|
400
|
+
addCommands() {
|
|
401
|
+
return {
|
|
402
|
+
insertCustomText: async (text: string) => {
|
|
403
|
+
this.insertText(text)
|
|
404
|
+
await this.updateView()
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
const editor = await Editor.configure({
|
|
411
|
+
el: '#editor',
|
|
412
|
+
value: '',
|
|
413
|
+
extensions: [myExtension]
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
editor.commands.insertCustomText('Hello!')
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## 自定义样式
|
|
422
|
+
|
|
423
|
+
编辑器样式通过 CSS 变量管理,覆盖 `.kaitify` 下的变量即可修改主题:
|
|
424
|
+
|
|
425
|
+
```css
|
|
426
|
+
.kaitify {
|
|
427
|
+
--kaitify-theme: #308af3;
|
|
428
|
+
--kaitify-font-color: #505050;
|
|
429
|
+
--kaitify-border-color: #dedede;
|
|
430
|
+
--kaitify-background-color: #fff;
|
|
431
|
+
--kaitify-line-height: 1.5;
|
|
432
|
+
--kaitify-font-size: 14px;
|
|
433
|
+
--kaitify-border-radius: 3px;
|
|
434
|
+
--kaitify-font-family: PingFang SC, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/* 深色模式 */
|
|
438
|
+
.kaitify.kaitify-dark {
|
|
439
|
+
--kaitify-font-color: #f5f5f5;
|
|
440
|
+
--kaitify-border-color: #3b3b3b;
|
|
441
|
+
--kaitify-background-color: #1b1b1f;
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## 与前端框架集成
|
|
448
|
+
|
|
449
|
+
kaitify 不依赖任何框架,以 Vue3 为例:
|
|
450
|
+
|
|
451
|
+
```html
|
|
452
|
+
<template>
|
|
453
|
+
<div ref="editorEl" style="width:100%;height:300px;" />
|
|
454
|
+
</template>
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
```ts
|
|
458
|
+
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
459
|
+
import { Editor } from '@kaitify/core'
|
|
460
|
+
|
|
461
|
+
const editorEl = ref<HTMLElement>()
|
|
462
|
+
let editor: Editor | undefined
|
|
463
|
+
|
|
464
|
+
onMounted(async () => {
|
|
465
|
+
editor = await Editor.configure({
|
|
466
|
+
el: editorEl.value!,
|
|
467
|
+
value: '',
|
|
468
|
+
placeholder: '请输入内容...'
|
|
469
|
+
})
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
onBeforeUnmount(() => {
|
|
473
|
+
editor?.destroy()
|
|
474
|
+
})
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## 更多内容
|
|
480
|
+
|
|
481
|
+
完整的 API 文档、扩展详情、进阶用法等内容,请访问[官方文档](https://www.so-better.cn/docs/kaitify-core/)。
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## 更新日志
|
|
486
|
+
|
|
487
|
+
查看[更新日志](./docs/changelog.md)
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## License
|
|
492
|
+
|
|
493
|
+
[MIT](./LICENSE) © [so-better](https://github.com/so-better)
|
|
@@ -60,7 +60,7 @@ export type ExtensionCreateOptionType = {
|
|
|
60
60
|
*/
|
|
61
61
|
onPasteKeepStyles?: (this: Editor, node: KNode) => KNodeStylesType;
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
63
|
+
* 视图更新前回调
|
|
64
64
|
*/
|
|
65
65
|
onBeforeUpdateView?: (this: Editor) => void;
|
|
66
66
|
/**
|
|
@@ -68,7 +68,7 @@ export type ExtensionCreateOptionType = {
|
|
|
68
68
|
*/
|
|
69
69
|
onAfterUpdateView?: (this: Editor) => void;
|
|
70
70
|
/**
|
|
71
|
-
*
|
|
71
|
+
* 在删除和换行操作中块节点从其父节点中抽离出去成为与父节点同级的节点后触发,如果返回true则表示继续使用默认逻辑,会将该节点转为段落,返回false则不走默认逻辑,需要自定义处理
|
|
72
72
|
*/
|
|
73
73
|
onDetachMentBlockFromParent?: (this: Editor, node: KNode) => boolean;
|
|
74
74
|
/**
|
|
@@ -149,7 +149,7 @@ export declare class Extension {
|
|
|
149
149
|
*/
|
|
150
150
|
onPasteKeepStyles?: (this: Editor, node: KNode) => KNodeStylesType;
|
|
151
151
|
/**
|
|
152
|
-
*
|
|
152
|
+
* 视图更新前回调
|
|
153
153
|
*/
|
|
154
154
|
onBeforeUpdateView?: (this: Editor) => void;
|
|
155
155
|
/**
|
|
@@ -157,7 +157,7 @@ export declare class Extension {
|
|
|
157
157
|
*/
|
|
158
158
|
onAfterUpdateView?: (this: Editor) => void;
|
|
159
159
|
/**
|
|
160
|
-
*
|
|
160
|
+
* 在删除和换行操作中块节点从其父节点中抽离出去成为与父节点同级的节点后触发,如果返回true则表示继续使用默认逻辑,会将该节点转为段落,返回false则不走默认逻辑,需要自定义处理
|
|
161
161
|
*/
|
|
162
162
|
onDetachMentBlockFromParent?: (this: Editor, node: KNode) => boolean;
|
|
163
163
|
/**
|
|
@@ -26,7 +26,7 @@ declare module '../../model' {
|
|
|
26
26
|
/**
|
|
27
27
|
* 更新光标所在代码块的语言类型
|
|
28
28
|
*/
|
|
29
|
-
updateCodeBlockLanguage?: (language
|
|
29
|
+
updateCodeBlockLanguage?: (language?: HljsLanguageType) => Promise<void>;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
export type CodeBlockExtensionPropsType = {
|