vue-editify 0.0.50 → 0.1.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/examples/App.vue +27 -45
- package/lib/editify.es.js +6877 -7829
- package/lib/editify.umd.js +1 -1
- package/lib/style.css +1 -1
- package/package.json +2 -2
- package/src/Editify.vue +262 -1240
- package/src/components/{bussiness/Menu.vue → Menu.vue} +238 -139
- package/src/components/{bussiness/Toolbar.vue → Toolbar.vue} +227 -141
- package/src/components/base/Button.vue +6 -6
- package/src/components/base/Checkbox.vue +4 -4
- package/src/components/base/Layer.vue +12 -12
- package/src/components/{bussiness → common}/InsertImage.vue +7 -7
- package/src/components/{bussiness → common}/InsertVideo.vue +7 -7
- package/src/core/function.js +1044 -0
- package/src/core/rule.js +239 -0
- package/src/core/{index.js → tool.js} +60 -296
- package/src/index.js +1 -1
- /package/src/components/{bussiness → common}/Colors.vue +0 -0
- /package/src/components/{bussiness → common}/InsertLink.vue +0 -0
- /package/src/components/{bussiness → common}/InsertTable.vue +0 -0
package/src/Editify.vue
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
<template>
|
2
|
-
<div class="editify" :class="{
|
2
|
+
<div class="editify" :class="{ fullscreen: isFullScreen }">
|
3
3
|
<!-- 菜单区域 -->
|
4
|
-
<Menu v-if="menuConfig.use" :config="menuConfig" :
|
4
|
+
<Menu v-if="menuConfig.use" :config="menuConfig" :color="color" ref="menu"></Menu>
|
5
5
|
<!-- 编辑层,与编辑区域宽高相同必须适配 -->
|
6
6
|
<div ref="body" class="editify-body" :class="{ border: showBorder, menu_inner: menuConfig.use && menuConfig.mode == 'inner' }" :data-editify-uid="uid">
|
7
7
|
<!-- 编辑器 -->
|
8
|
-
<div ref="content" class="editify-content" :class="{ placeholder: showPlaceholder, disabled: disabled }"
|
8
|
+
<div ref="content" class="editify-content" :class="{ placeholder: showPlaceholder, disabled: disabled }" @keydown="handleEditorKeydown" @click="handleEditorClick" @compositionstart="isInputChinese = true" @compositionend="isInputChinese = false" :data-editify-placeholder="placeholder"></div>
|
9
9
|
<!-- 代码视图 -->
|
10
10
|
<textarea v-if="isSourceView" :value="value" readonly class="editify-source" />
|
11
11
|
<!-- 工具条 -->
|
@@ -21,16 +21,18 @@
|
|
21
21
|
<script>
|
22
22
|
import { getCurrentInstance } from 'vue'
|
23
23
|
import { AlexEditor, AlexElement } from 'alex-editor'
|
24
|
-
import
|
25
|
-
import { pasteKeepData, editorProps,
|
26
|
-
import
|
24
|
+
import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor } from 'dap-util'
|
25
|
+
import { pasteKeepData, editorProps, mergeObject, getToolbarConfig, getMenuConfig } from './core/tool'
|
26
|
+
import { parseList, orderdListHandle, mediaHandle, tableHandle, preHandle, specialInblockHandle } from './core/rule'
|
27
|
+
import { isTask, elementToParagraph, getCurrentParsedomElement, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange, setIndentIncrease, setIndentDecrease, insertImage, insertVideo } from './core/function'
|
27
28
|
import Tooltip from './components/base/Tooltip'
|
28
|
-
import
|
29
|
+
import Toolbar from './components/Toolbar'
|
30
|
+
import Menu from './components/Menu'
|
29
31
|
|
30
32
|
export default {
|
31
33
|
name: 'editify',
|
32
34
|
props: { ...editorProps },
|
33
|
-
emits: ['update:modelValue', 'focus', 'blur', 'change', 'keydown', 'insertparagraph', 'rangeupdate', '
|
35
|
+
emits: ['update:modelValue', 'focus', 'blur', 'change', 'keydown', 'insertparagraph', 'rangeupdate', 'updateview'],
|
34
36
|
setup() {
|
35
37
|
const instance = getCurrentInstance()
|
36
38
|
return {
|
@@ -39,14 +41,8 @@ export default {
|
|
39
41
|
},
|
40
42
|
data() {
|
41
43
|
return {
|
42
|
-
//编辑器对象
|
43
|
-
editor: null,
|
44
44
|
//是否编辑器内部修改值
|
45
45
|
isModelChange: false,
|
46
|
-
//是否代码视图
|
47
|
-
isSourceView: false,
|
48
|
-
//是否全屏
|
49
|
-
isFullScreen: false,
|
50
46
|
//是否正在输入中文
|
51
47
|
isInputChinese: false,
|
52
48
|
//表格列宽拖拽记录数据
|
@@ -63,12 +59,22 @@ export default {
|
|
63
59
|
//类型
|
64
60
|
type: 'text'
|
65
61
|
},
|
66
|
-
|
67
|
-
|
62
|
+
|
63
|
+
/** 以下是可对外使用的属性 */
|
64
|
+
|
65
|
+
//编辑器对象
|
66
|
+
editor: null,
|
67
|
+
//是否代码视图
|
68
|
+
isSourceView: false,
|
69
|
+
//是否全屏
|
70
|
+
isFullScreen: false,
|
68
71
|
//菜单栏是否可以使用标识
|
69
72
|
canUseMenu: false,
|
70
|
-
|
71
|
-
|
73
|
+
//光标选取范围内的元素数组
|
74
|
+
dataRangeCaches: {
|
75
|
+
flatList: [],
|
76
|
+
list: []
|
77
|
+
}
|
72
78
|
}
|
73
79
|
},
|
74
80
|
computed: {
|
@@ -83,7 +89,7 @@ export default {
|
|
83
89
|
},
|
84
90
|
//编辑器的纯文本值
|
85
91
|
textValue() {
|
86
|
-
return
|
92
|
+
return DapElement.string2dom(`<div>${this.value}</div>`).innerText
|
87
93
|
},
|
88
94
|
//是否显示占位符
|
89
95
|
showPlaceholder() {
|
@@ -103,15 +109,6 @@ export default {
|
|
103
109
|
}
|
104
110
|
return this.border
|
105
111
|
},
|
106
|
-
//编辑器样式设置
|
107
|
-
contentStyle() {
|
108
|
-
if (this.height === true || this.isFullScreen) {
|
109
|
-
return {
|
110
|
-
height: this.contentHeight + 'px'
|
111
|
-
}
|
112
|
-
}
|
113
|
-
return this.autoheight ? { minHeight: this.height } : { height: this.height }
|
114
|
-
},
|
115
112
|
//最终生效的工具栏配置
|
116
113
|
toolbarConfig() {
|
117
114
|
return mergeObject(getToolbarConfig(this.$editTrans, this.$editLocale), this.toolbar || {})
|
@@ -140,6 +137,7 @@ export default {
|
|
140
137
|
this.editor.formatElementStack()
|
141
138
|
this.editor.domRender()
|
142
139
|
this.editor.rangeRender()
|
140
|
+
this.$refs.content.blur()
|
143
141
|
},
|
144
142
|
//代码视图切换
|
145
143
|
isSourceView(newValue) {
|
@@ -151,19 +149,12 @@ export default {
|
|
151
149
|
}
|
152
150
|
}
|
153
151
|
},
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
this.
|
158
|
-
}
|
159
|
-
|
160
|
-
//监听height为true
|
161
|
-
height: {
|
162
|
-
immediate: true,
|
163
|
-
handler: function () {
|
164
|
-
this.$nextTick(() => {
|
165
|
-
this.setContentHeight()
|
166
|
-
})
|
152
|
+
//监听disabled
|
153
|
+
disabled(newValue) {
|
154
|
+
if (newValue) {
|
155
|
+
this.editor.setDisabled()
|
156
|
+
} else {
|
157
|
+
this.editor.setEnabled()
|
167
158
|
}
|
168
159
|
}
|
169
160
|
},
|
@@ -173,71 +164,17 @@ export default {
|
|
173
164
|
//监听滚动隐藏工具条
|
174
165
|
this.handleScroll()
|
175
166
|
//鼠标按下监听
|
176
|
-
|
167
|
+
DapEvent.on(document.documentElement, `mousedown.editify_${this.uid}`, this.documentMouseDown)
|
177
168
|
//鼠标移动监听
|
178
|
-
|
169
|
+
DapEvent.on(document.documentElement, `mousemove.editify_${this.uid}`, this.documentMouseMove)
|
179
170
|
//鼠标松开监听
|
180
|
-
|
171
|
+
DapEvent.on(document.documentElement, `mouseup.editify_${this.uid}`, this.documentMouseUp)
|
181
172
|
//鼠标点击箭头
|
182
|
-
|
173
|
+
DapEvent.on(document.documentElement, `click.editify_${this.uid}`, this.documentClick)
|
183
174
|
//监听窗口改变
|
184
|
-
|
185
|
-
this.setVideoHeight()
|
186
|
-
this.setContentHeight()
|
187
|
-
})
|
175
|
+
DapEvent.on(window, `resize.editify_${this.uid}`, this.setVideoHeight)
|
188
176
|
},
|
189
177
|
methods: {
|
190
|
-
//初始创建编辑器
|
191
|
-
createEditor() {
|
192
|
-
//创建编辑器
|
193
|
-
this.editor = new AlexEditor(this.$refs.content, {
|
194
|
-
value: this.value,
|
195
|
-
disabled: this.disabled,
|
196
|
-
renderRules: [
|
197
|
-
parseList,
|
198
|
-
mediaHandle,
|
199
|
-
tableHandle,
|
200
|
-
el => {
|
201
|
-
preHandle.apply(this.editor, [el, this.toolbarConfig?.use && this.toolbarConfig?.codeBlock?.languages?.show, this.toolbarConfig?.codeBlock?.languages.options])
|
202
|
-
},
|
203
|
-
...this.renderRules
|
204
|
-
],
|
205
|
-
allowCopy: this.allowCopy,
|
206
|
-
allowPaste: this.allowPaste,
|
207
|
-
allowCut: this.allowCut,
|
208
|
-
allowPasteHtml: this.allowPasteHtml,
|
209
|
-
allowPasteHtml: this.allowPasteHtml,
|
210
|
-
customImagePaste: this.customImagePaste,
|
211
|
-
customVideoPaste: this.customVideoPaste,
|
212
|
-
customMerge: this.handleCustomMerge,
|
213
|
-
customParseNode: this.handleCustomParseNode
|
214
|
-
})
|
215
|
-
//编辑器渲染后会有一个渲染过程,会改变内容,因此重新获取内容的值来设置value
|
216
|
-
this.internalModify(this.editor.value)
|
217
|
-
//设置监听事件
|
218
|
-
this.editor.on('change', this.handleEditorChange)
|
219
|
-
this.editor.on('focus', this.handleEditorFocus)
|
220
|
-
this.editor.on('blur', this.handleEditorBlur)
|
221
|
-
this.editor.on('insertParagraph', this.handleInsertParagraph)
|
222
|
-
this.editor.on('rangeUpdate', this.handleRangeUpdate)
|
223
|
-
this.editor.on('copy', this.handleCopy)
|
224
|
-
this.editor.on('cut', this.handleCut)
|
225
|
-
this.editor.on('pasteText', this.handlePasteText)
|
226
|
-
this.editor.on('pasteHtml', this.handlePasteHtml)
|
227
|
-
this.editor.on('pasteImage', this.handlePasteImage)
|
228
|
-
this.editor.on('pasteVideo', this.handlePasteVideo)
|
229
|
-
this.editor.on('deleteInStart', this.handleDeleteInStart)
|
230
|
-
this.editor.on('deleteComplete', this.handleDeleteComplete)
|
231
|
-
this.editor.on('beforeRender', this.handleBeforeRender)
|
232
|
-
this.editor.on('afterRender', this.handleAfterRender)
|
233
|
-
//格式化和dom渲染
|
234
|
-
this.editor.formatElementStack()
|
235
|
-
this.editor.domRender()
|
236
|
-
//自动获取焦点
|
237
|
-
if (this.autofocus && !this.isSourceView && !this.disabled) {
|
238
|
-
this.collapseToEnd()
|
239
|
-
}
|
240
|
-
},
|
241
178
|
//编辑器内部修改值的方法
|
242
179
|
internalModify(val) {
|
243
180
|
this.isModelChange = true
|
@@ -246,10 +183,15 @@ export default {
|
|
246
183
|
this.isModelChange = false
|
247
184
|
})
|
248
185
|
},
|
186
|
+
//隐藏工具条
|
187
|
+
hideToolbar() {
|
188
|
+
this.toolbarOptions.show = false
|
189
|
+
this.toolbarOptions.node = null
|
190
|
+
},
|
249
191
|
//监听滚动隐藏工具条
|
250
192
|
handleScroll() {
|
251
193
|
const setScroll = el => {
|
252
|
-
|
194
|
+
DapEvent.on(el, `scroll.editify_${this.uid}`, () => {
|
253
195
|
if (this.toolbarConfig.use && this.toolbarOptions.show) {
|
254
196
|
this.hideToolbar()
|
255
197
|
}
|
@@ -263,7 +205,7 @@ export default {
|
|
263
205
|
//移除上述滚动事件的监听
|
264
206
|
removeScrollHandle() {
|
265
207
|
const removeScroll = el => {
|
266
|
-
|
208
|
+
DapEvent.off(el, `scroll.editify_${this.uid}`)
|
267
209
|
if (el.parentNode) {
|
268
210
|
removeScroll(el.parentNode)
|
269
211
|
}
|
@@ -271,17 +213,17 @@ export default {
|
|
271
213
|
removeScroll(this.$refs.content)
|
272
214
|
},
|
273
215
|
//工具条显示判断
|
274
|
-
handleToolbar(
|
216
|
+
handleToolbar() {
|
275
217
|
if (this.disabled || this.isSourceView) {
|
276
218
|
return
|
277
219
|
}
|
278
220
|
this.hideToolbar()
|
279
221
|
this.$nextTick(() => {
|
280
|
-
const table =
|
281
|
-
const pre =
|
282
|
-
const link =
|
283
|
-
const image =
|
284
|
-
const video =
|
222
|
+
const table = getCurrentParsedomElement(this, 'table')
|
223
|
+
const pre = getCurrentParsedomElement(this, 'pre')
|
224
|
+
const link = getCurrentParsedomElement(this, 'a')
|
225
|
+
const image = getCurrentParsedomElement(this, 'img')
|
226
|
+
const video = getCurrentParsedomElement(this, 'video')
|
285
227
|
if (link) {
|
286
228
|
this.toolbarOptions.type = 'link'
|
287
229
|
this.toolbarOptions.node = `[data-editify-uid="${this.uid}"] [data-editify-element="${link.key}"]`
|
@@ -323,10 +265,10 @@ export default {
|
|
323
265
|
this.toolbarOptions.show = true
|
324
266
|
}
|
325
267
|
} else {
|
326
|
-
const result = this.
|
268
|
+
const result = this.dataRangeCaches.flatList.filter(item => {
|
327
269
|
return item.element.isText()
|
328
270
|
})
|
329
|
-
if (result.length && !this
|
271
|
+
if (result.length && !hasTableInRange(this) && !hasPreInRange(this) && !hasLinkInRange(this) && !hasImageInRange(this) && !hasVideoInRange(this)) {
|
330
272
|
this.toolbarOptions.type = 'text'
|
331
273
|
if (this.toolbarOptions.show) {
|
332
274
|
this.$refs.toolbar.$refs.layer.setPosition()
|
@@ -337,41 +279,67 @@ export default {
|
|
337
279
|
}
|
338
280
|
})
|
339
281
|
},
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
} else {
|
346
|
-
preEle.children.push(...ele.children)
|
347
|
-
preEle.children.forEach(item => {
|
348
|
-
item.parent = preEle
|
349
|
-
})
|
350
|
-
ele.children = null
|
351
|
-
}
|
282
|
+
//设定编辑器内的视频高度
|
283
|
+
setVideoHeight() {
|
284
|
+
this.$refs.content.querySelectorAll('video').forEach(video => {
|
285
|
+
video.style.height = video.offsetWidth / this.videoRatio + 'px'
|
286
|
+
})
|
352
287
|
},
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
288
|
+
//初始创建编辑器
|
289
|
+
createEditor() {
|
290
|
+
//创建编辑器
|
291
|
+
this.editor = new AlexEditor(this.$refs.content, {
|
292
|
+
value: this.value,
|
293
|
+
disabled: this.disabled,
|
294
|
+
renderRules: [
|
295
|
+
el => {
|
296
|
+
parseList(this.editor, el)
|
297
|
+
},
|
298
|
+
el => {
|
299
|
+
orderdListHandle(this.editor, el)
|
300
|
+
},
|
301
|
+
el => {
|
302
|
+
mediaHandle(this.editor, el)
|
303
|
+
},
|
304
|
+
el => {
|
305
|
+
tableHandle(this.editor, el)
|
306
|
+
},
|
307
|
+
el => {
|
308
|
+
preHandle(this.editor, el, this.toolbarConfig?.use && this.toolbarConfig?.codeBlock?.languages?.show, this.toolbarConfig?.codeBlock?.languages.options)
|
309
|
+
},
|
310
|
+
el => {
|
311
|
+
specialInblockHandle(this.editor, el)
|
312
|
+
}
|
313
|
+
],
|
314
|
+
allowCopy: this.allowCopy,
|
315
|
+
allowPaste: this.allowPaste,
|
316
|
+
allowCut: this.allowCut,
|
317
|
+
allowPasteHtml: this.allowPasteHtml,
|
318
|
+
allowPasteHtml: this.allowPasteHtml,
|
319
|
+
customImagePaste: this.handleCustomImagePaste,
|
320
|
+
customVideoPaste: this.handleCustomVideoPaste,
|
321
|
+
customMerge: this.handleCustomMerge,
|
322
|
+
customParseNode: this.handleCustomParseNode
|
323
|
+
})
|
324
|
+
//编辑器渲染后会有一个渲染过程,会改变内容,因此重新获取内容的值来设置value
|
325
|
+
this.internalModify(this.editor.value)
|
326
|
+
//设置监听事件
|
327
|
+
this.editor.on('change', this.handleEditorChange)
|
328
|
+
this.editor.on('focus', this.handleEditorFocus)
|
329
|
+
this.editor.on('blur', this.handleEditorBlur)
|
330
|
+
this.editor.on('insertParagraph', this.handleInsertParagraph)
|
331
|
+
this.editor.on('rangeUpdate', this.handleRangeUpdate)
|
332
|
+
this.editor.on('pasteHtml', this.handlePasteHtml)
|
333
|
+
this.editor.on('deleteInStart', this.handleDeleteInStart)
|
334
|
+
this.editor.on('deleteComplete', this.handleDeleteComplete)
|
335
|
+
this.editor.on('afterRender', this.handleAfterRender)
|
336
|
+
//格式化和dom渲染
|
337
|
+
this.editor.formatElementStack()
|
338
|
+
this.editor.domRender()
|
339
|
+
//自动获取焦点
|
340
|
+
if (this.autofocus && !this.isSourceView && !this.disabled) {
|
341
|
+
this.collapseToEnd()
|
368
342
|
}
|
369
|
-
return ele
|
370
|
-
},
|
371
|
-
//隐藏工具条
|
372
|
-
hideToolbar() {
|
373
|
-
this.toolbarOptions.show = false
|
374
|
-
this.toolbarOptions.node = null
|
375
343
|
},
|
376
344
|
//鼠标在页面按下:处理表格拖拽改变列宽和菜单栏是否使用判断
|
377
345
|
documentMouseDown(e) {
|
@@ -379,9 +347,9 @@ export default {
|
|
379
347
|
return
|
380
348
|
}
|
381
349
|
//鼠标在编辑器内按下
|
382
|
-
if (
|
350
|
+
if (DapElement.isContains(this.$refs.content, e.target)) {
|
383
351
|
const elm = e.target
|
384
|
-
const key =
|
352
|
+
const key = DapData.get(elm, 'data-alex-editor-key')
|
385
353
|
if (key) {
|
386
354
|
const element = this.editor.getElementByKey(key)
|
387
355
|
if (element && element.parsedom == 'td') {
|
@@ -390,7 +358,7 @@ export default {
|
|
390
358
|
if (element.parent.children[length - 1].isEqual(element)) {
|
391
359
|
return
|
392
360
|
}
|
393
|
-
const rect =
|
361
|
+
const rect = DapElement.getElementBounding(elm)
|
394
362
|
//在可拖拽范围内
|
395
363
|
if (e.pageX >= Math.abs(rect.left + elm.offsetWidth - 5) && e.pageX <= Math.abs(rect.left + elm.offsetWidth + 5)) {
|
396
364
|
this.tableColumnResizeParams.element = element
|
@@ -400,7 +368,7 @@ export default {
|
|
400
368
|
}
|
401
369
|
}
|
402
370
|
//如果点击了除编辑器外的地方,菜单栏不可使用
|
403
|
-
if (!
|
371
|
+
if (!DapElement.isContains(this.$el, e.target) && !this.isSourceView) {
|
404
372
|
this.canUseMenu = false
|
405
373
|
}
|
406
374
|
},
|
@@ -412,7 +380,7 @@ export default {
|
|
412
380
|
if (!this.tableColumnResizeParams.element) {
|
413
381
|
return
|
414
382
|
}
|
415
|
-
const table =
|
383
|
+
const table = getCurrentParsedomElement(this, 'table')
|
416
384
|
if (!table) {
|
417
385
|
return
|
418
386
|
}
|
@@ -428,14 +396,14 @@ export default {
|
|
428
396
|
this.tableColumnResizeParams.start = e.pageX
|
429
397
|
},
|
430
398
|
//鼠标在页面松开:处理表格拖拽改变列宽
|
431
|
-
documentMouseUp(
|
399
|
+
documentMouseUp() {
|
432
400
|
if (this.disabled) {
|
433
401
|
return
|
434
402
|
}
|
435
403
|
if (!this.tableColumnResizeParams.element) {
|
436
404
|
return
|
437
405
|
}
|
438
|
-
const table =
|
406
|
+
const table = getCurrentParsedomElement(this, 'table')
|
439
407
|
if (!table) {
|
440
408
|
return
|
441
409
|
}
|
@@ -460,17 +428,17 @@ export default {
|
|
460
428
|
if (this.disabled) {
|
461
429
|
return
|
462
430
|
}
|
463
|
-
|
464
|
-
if (
|
431
|
+
//鼠标在编辑器内点击
|
432
|
+
if (DapElement.isContains(this.$refs.content, e.target)) {
|
465
433
|
const elm = e.target
|
466
|
-
const key =
|
434
|
+
const key = DapData.get(elm, 'data-alex-editor-key')
|
467
435
|
if (key) {
|
468
436
|
const element = this.editor.getElementByKey(key)
|
469
437
|
//如果是任务列表元素
|
470
|
-
if (
|
471
|
-
const rect =
|
438
|
+
if (isTask(element)) {
|
439
|
+
const rect = DapElement.getElementBounding(elm)
|
472
440
|
//在复选框范围内
|
473
|
-
if (e.pageX >= Math.abs(rect.left) && e.pageX <= Math.abs(rect.left + 16) && e.pageY >= Math.abs(rect.top +
|
441
|
+
if (e.pageX >= Math.abs(rect.left) && e.pageX <= Math.abs(rect.left + 16) && e.pageY >= Math.abs(rect.top + 2) && e.pageY <= Math.abs(rect.top + 18)) {
|
474
442
|
//取消勾选
|
475
443
|
if (element.marks['data-editify-task'] == 'checked') {
|
476
444
|
element.marks['data-editify-task'] = 'uncheck'
|
@@ -492,6 +460,99 @@ export default {
|
|
492
460
|
}
|
493
461
|
}
|
494
462
|
},
|
463
|
+
//自定义图片粘贴
|
464
|
+
async handleCustomImagePaste(url) {
|
465
|
+
const newUrl = await this.customImagePaste.apply(this, [url])
|
466
|
+
if (newUrl) {
|
467
|
+
insertImage(this, newUrl)
|
468
|
+
}
|
469
|
+
},
|
470
|
+
//自定义视频粘贴
|
471
|
+
async handleCustomVideoPaste(url) {
|
472
|
+
const newUrl = await this.customVideoPaste.apply(this, [url])
|
473
|
+
if (newUrl) {
|
474
|
+
insertVideo(this, newUrl)
|
475
|
+
}
|
476
|
+
},
|
477
|
+
//重新定义编辑器合并元素的逻辑
|
478
|
+
handleCustomMerge(ele, preEle) {
|
479
|
+
const uneditable = preEle.getUneditableElement()
|
480
|
+
if (uneditable) {
|
481
|
+
uneditable.toEmpty()
|
482
|
+
} else {
|
483
|
+
preEle.children.push(...ele.children)
|
484
|
+
preEle.children.forEach(item => {
|
485
|
+
item.parent = preEle
|
486
|
+
})
|
487
|
+
ele.children = null
|
488
|
+
}
|
489
|
+
},
|
490
|
+
//针对node转为元素进行额外的处理
|
491
|
+
handleCustomParseNode(ele) {
|
492
|
+
if (ele.parsedom == 'code') {
|
493
|
+
ele.parsedom = 'span'
|
494
|
+
const marks = {
|
495
|
+
'data-editify-code': true
|
496
|
+
}
|
497
|
+
if (ele.hasMarks()) {
|
498
|
+
Object.assign(ele.marks, marks)
|
499
|
+
} else {
|
500
|
+
ele.marks = marks
|
501
|
+
}
|
502
|
+
}
|
503
|
+
if (typeof this.customParseNoe == 'function') {
|
504
|
+
ele = this.customParseNoe.apply(this, [ele])
|
505
|
+
}
|
506
|
+
return ele
|
507
|
+
},
|
508
|
+
//编辑区域键盘按下:设置缩进快捷键
|
509
|
+
handleEditorKeydown(e) {
|
510
|
+
if (this.disabled) {
|
511
|
+
return
|
512
|
+
}
|
513
|
+
//增加缩进
|
514
|
+
if (e.keyCode == 9 && !e.metaKey && !e.shiftKey && !e.ctrlKey && !e.altKey) {
|
515
|
+
e.preventDefault()
|
516
|
+
if (!hasTableInRange(this)) {
|
517
|
+
setIndentIncrease(this)
|
518
|
+
this.editor.formatElementStack()
|
519
|
+
this.editor.domRender()
|
520
|
+
this.editor.rangeRender()
|
521
|
+
}
|
522
|
+
}
|
523
|
+
//减少缩进
|
524
|
+
else if (e.keyCode == 9 && !e.metaKey && e.shiftKey && !e.ctrlKey && !e.altKey) {
|
525
|
+
e.preventDefault()
|
526
|
+
if (!hasTableInRange(this)) {
|
527
|
+
setIndentDecrease(this)
|
528
|
+
this.editor.formatElementStack()
|
529
|
+
this.editor.domRender()
|
530
|
+
this.editor.rangeRender()
|
531
|
+
}
|
532
|
+
}
|
533
|
+
//自定义键盘按下操作
|
534
|
+
this.$emit('keydown', e)
|
535
|
+
},
|
536
|
+
//点击编辑器:处理图片和视频的光标聚集
|
537
|
+
handleEditorClick(e) {
|
538
|
+
if (this.disabled || this.isSourceView) {
|
539
|
+
return
|
540
|
+
}
|
541
|
+
const node = e.target
|
542
|
+
//点击的是图片或者视频
|
543
|
+
if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
|
544
|
+
const key = Number(node.getAttribute('data-editify-element'))
|
545
|
+
if (DapNumber.isNumber(key)) {
|
546
|
+
const element = this.editor.getElementByKey(key)
|
547
|
+
if (!this.editor.range) {
|
548
|
+
this.editor.initRange()
|
549
|
+
}
|
550
|
+
this.editor.range.anchor.moveToStart(element)
|
551
|
+
this.editor.range.focus.moveToEnd(element)
|
552
|
+
this.editor.rangeRender()
|
553
|
+
}
|
554
|
+
}
|
555
|
+
},
|
495
556
|
//编辑器的值更新
|
496
557
|
handleEditorChange(newVal, oldVal) {
|
497
558
|
if (this.disabled) {
|
@@ -529,7 +590,7 @@ export default {
|
|
529
590
|
//编辑区域边框颜色
|
530
591
|
this.$refs.body.style.borderColor = this.color
|
531
592
|
//转换颜色值
|
532
|
-
const rgb =
|
593
|
+
const rgb = DapColor.hex2rgb(this.color)
|
533
594
|
//菜单栏模式为inner
|
534
595
|
if (this.menuConfig.use && this.menuConfig.mode == 'inner') {
|
535
596
|
//编辑区域除顶部边框的阴影
|
@@ -553,56 +614,15 @@ export default {
|
|
553
614
|
//获取焦点时可以使用菜单栏
|
554
615
|
setTimeout(() => {
|
555
616
|
this.canUseMenu = true
|
617
|
+
this.$emit('focus', val)
|
556
618
|
}, 0)
|
557
|
-
this.$emit('focus', val)
|
558
|
-
},
|
559
|
-
//编辑区域键盘按下
|
560
|
-
handleEditorKeydown(e) {
|
561
|
-
if (this.disabled) {
|
562
|
-
return
|
563
|
-
}
|
564
|
-
//增加缩进
|
565
|
-
if (e.keyCode == 9 && !e.metaKey && !e.shiftKey && !e.ctrlKey && !e.altKey) {
|
566
|
-
e.preventDefault()
|
567
|
-
this.setIndentIncrease()
|
568
|
-
}
|
569
|
-
//减少缩进
|
570
|
-
else if (e.keyCode == 9 && !e.metaKey && e.shiftKey && !e.ctrlKey && !e.altKey) {
|
571
|
-
e.preventDefault()
|
572
|
-
this.setIndentDecrease()
|
573
|
-
}
|
574
|
-
//自定义键盘按下操作
|
575
|
-
this.$emit('keydown', e)
|
576
|
-
},
|
577
|
-
//点击编辑器
|
578
|
-
handleEditorClick(e) {
|
579
|
-
if (this.disabled || this.isSourceView) {
|
580
|
-
return
|
581
|
-
}
|
582
|
-
const node = e.target
|
583
|
-
//点击的是图片或者视频
|
584
|
-
if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
|
585
|
-
const key = node.getAttribute('data-editify-element')
|
586
|
-
if (key) {
|
587
|
-
const element = this.editor.getElementByKey(key)
|
588
|
-
if (!this.editor.range) {
|
589
|
-
this.editor.initRange()
|
590
|
-
}
|
591
|
-
this.editor.range.anchor.moveToStart(element)
|
592
|
-
this.editor.range.focus.moveToEnd(element)
|
593
|
-
this.editor.rangeRender()
|
594
|
-
}
|
595
|
-
}
|
596
619
|
},
|
597
620
|
//编辑器换行
|
598
621
|
handleInsertParagraph(element, previousElement) {
|
599
622
|
//前一个块元素如果是只包含换行符的元素,并且当前块元素也是包含换行符的元素,则当前块元素转为段落
|
600
623
|
if (previousElement.isOnlyHasBreak() && element.isOnlyHasBreak()) {
|
601
|
-
if (!previousElement.isBlock()) {
|
602
|
-
previousElement.convertToBlock()
|
603
|
-
}
|
604
624
|
if (previousElement.parsedom != AlexElement.BLOCK_NODE) {
|
605
|
-
|
625
|
+
elementToParagraph(previousElement)
|
606
626
|
this.editor.range.anchor.moveToStart(previousElement)
|
607
627
|
this.editor.range.focus.moveToStart(previousElement)
|
608
628
|
element.toEmpty()
|
@@ -615,37 +635,31 @@ export default {
|
|
615
635
|
if (this.disabled) {
|
616
636
|
return
|
617
637
|
}
|
618
|
-
|
619
|
-
|
638
|
+
|
639
|
+
//如果没有range禁用菜单栏
|
640
|
+
this.canUseMenu = !!this.editor.range
|
641
|
+
|
642
|
+
//没有range直接返回
|
643
|
+
if (!this.editor.range) {
|
644
|
+
return
|
620
645
|
}
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
//如果使用菜单栏
|
631
|
-
if (this.menuConfig.use) {
|
632
|
-
this.$refs.menu.handleRangeUpdate(true)
|
633
|
-
}
|
646
|
+
|
647
|
+
//获取光标选取范围内的元素数据,并且进行缓存
|
648
|
+
this.dataRangeCaches = this.editor.getElementsByRange()
|
649
|
+
|
650
|
+
//如果使用工具条或者菜单栏
|
651
|
+
if (this.toolbarConfig.use || this.menuConfig.use) {
|
652
|
+
//如果使用工具条
|
653
|
+
if (this.toolbarConfig.use) {
|
654
|
+
this.handleToolbar()
|
634
655
|
}
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
//编辑器剪切
|
643
|
-
handleCut(text, html) {
|
644
|
-
this.$emit('cut', text, html)
|
645
|
-
},
|
646
|
-
//编辑器粘贴纯文本
|
647
|
-
handlePasteText(data) {
|
648
|
-
this.$emit('paste-text', data)
|
656
|
+
//如果使用菜单栏
|
657
|
+
if (this.menuConfig.use) {
|
658
|
+
this.$refs.menu.handleRangeUpdate()
|
659
|
+
}
|
660
|
+
}
|
661
|
+
|
662
|
+
this.$emit('rangeupdate')
|
649
663
|
},
|
650
664
|
//编辑器粘贴html
|
651
665
|
handlePasteHtml(elements) {
|
@@ -672,20 +686,11 @@ export default {
|
|
672
686
|
el.styles = styles
|
673
687
|
}
|
674
688
|
})
|
675
|
-
this.$emit('paste-html', elements)
|
676
|
-
},
|
677
|
-
//编辑器粘贴图片
|
678
|
-
handlePasteImage(url) {
|
679
|
-
this.$emit('paste-image', url)
|
680
689
|
},
|
681
|
-
|
682
|
-
handlePasteVideo(url) {
|
683
|
-
this.$emit('paste-video', url)
|
684
|
-
},
|
685
|
-
//编辑器部分删除情景
|
690
|
+
//编辑器部分删除情景(在编辑器起始处)
|
686
691
|
handleDeleteInStart(element) {
|
687
692
|
if (element.isBlock()) {
|
688
|
-
|
693
|
+
elementToParagraph(element)
|
689
694
|
}
|
690
695
|
},
|
691
696
|
//编辑器删除完成后事件
|
@@ -695,39 +700,12 @@ export default {
|
|
695
700
|
uneditable.toEmpty()
|
696
701
|
}
|
697
702
|
},
|
698
|
-
//编辑器dom渲染之前
|
699
|
-
handleBeforeRender() {
|
700
|
-
this.$emit('before-render')
|
701
|
-
},
|
702
703
|
//编辑器dom渲染
|
703
704
|
handleAfterRender() {
|
704
705
|
//设定视频高度
|
705
706
|
this.setVideoHeight()
|
706
|
-
|
707
|
-
this.$emit('
|
708
|
-
},
|
709
|
-
//设定视频高度
|
710
|
-
setVideoHeight() {
|
711
|
-
this.$refs.content.querySelectorAll('video').forEach(video => {
|
712
|
-
video.style.height = video.offsetWidth / this.videoRatio + 'px'
|
713
|
-
})
|
714
|
-
},
|
715
|
-
//设置编辑器主体高度
|
716
|
-
setContentHeight() {
|
717
|
-
if (this.height === true || this.isFullScreen) {
|
718
|
-
let height = this.$el.offsetHeight
|
719
|
-
if (this.menuConfig.use) {
|
720
|
-
height -= this.$refs.menu.$el.offsetHeight
|
721
|
-
}
|
722
|
-
if (this.showWordLength) {
|
723
|
-
height -= this.$refs.footer.offsetHeight
|
724
|
-
}
|
725
|
-
if (this.$refs.menu.menuMode == 'default') {
|
726
|
-
height -= 10
|
727
|
-
}
|
728
|
-
//这里减去2px是因为body设了padding:1px
|
729
|
-
this.contentHeight = height - 2
|
730
|
-
}
|
707
|
+
|
708
|
+
this.$emit('updateview')
|
731
709
|
},
|
732
710
|
|
733
711
|
//api:光标设置到文档底部
|
@@ -737,7 +715,7 @@ export default {
|
|
737
715
|
}
|
738
716
|
this.editor.collapseToEnd()
|
739
717
|
this.editor.rangeRender()
|
740
|
-
|
718
|
+
DapElement.setScrollTop({
|
741
719
|
el: this.$refs.content,
|
742
720
|
number: 1000000,
|
743
721
|
time: 0
|
@@ -751,364 +729,13 @@ export default {
|
|
751
729
|
this.editor.collapseToStart()
|
752
730
|
this.editor.rangeRender()
|
753
731
|
this.$nextTick(() => {
|
754
|
-
|
732
|
+
DapElement.setScrollTop({
|
755
733
|
el: this.$refs.content,
|
756
734
|
number: 0,
|
757
735
|
time: 0
|
758
736
|
})
|
759
737
|
})
|
760
738
|
},
|
761
|
-
//api:获取某个元素是否在某个标签元素下,如果是返回该标签元素,否则返回null
|
762
|
-
getParsedomElementByElement(element, parsedom) {
|
763
|
-
if (element.isBlock()) {
|
764
|
-
return element.parsedom == parsedom ? element : null
|
765
|
-
}
|
766
|
-
if (!element.isText() && element.parsedom == parsedom) {
|
767
|
-
return element
|
768
|
-
}
|
769
|
-
return this.getParsedomElementByElement(element.parent, parsedom)
|
770
|
-
},
|
771
|
-
//api:获取光标是否在指定标签元素下,如果是返回该标签元素,否则返回null
|
772
|
-
getCurrentParsedomElement(parsedom, useCache = false) {
|
773
|
-
if (this.disabled) {
|
774
|
-
return null
|
775
|
-
}
|
776
|
-
if (!this.editor.range) {
|
777
|
-
return null
|
778
|
-
}
|
779
|
-
if (this.editor.range.anchor.element.isEqual(this.editor.range.focus.element)) {
|
780
|
-
return this.getParsedomElementByElement(this.editor.range.anchor.element, parsedom)
|
781
|
-
}
|
782
|
-
const arr = this.editor.getElementsByRange(useCache).includes.map(item => {
|
783
|
-
return this.getParsedomElementByElement(item.element, parsedom)
|
784
|
-
})
|
785
|
-
let hasNull = arr.some(el => {
|
786
|
-
return el == null
|
787
|
-
})
|
788
|
-
//如果存在null,则表示有的选区元素不在指定标签下,返回null
|
789
|
-
if (hasNull) {
|
790
|
-
return null
|
791
|
-
}
|
792
|
-
//如果只有一个元素,则返回该元素
|
793
|
-
if (arr.length == 1) {
|
794
|
-
return arr[0]
|
795
|
-
}
|
796
|
-
//默认数组中的元素都相等
|
797
|
-
let flag = true
|
798
|
-
for (let i = 1; i < arr.length; i++) {
|
799
|
-
if (!arr[i].isEqual(arr[0])) {
|
800
|
-
flag = false
|
801
|
-
break
|
802
|
-
}
|
803
|
-
}
|
804
|
-
//如果相等,则返回该元素
|
805
|
-
if (flag) {
|
806
|
-
return arr[0]
|
807
|
-
}
|
808
|
-
return null
|
809
|
-
},
|
810
|
-
//api:删除光标所在的指定标签元素
|
811
|
-
deleteByParsedom(parsedom, isRender = true, useCache = false) {
|
812
|
-
if (this.disabled) {
|
813
|
-
return
|
814
|
-
}
|
815
|
-
if (!this.editor.range) {
|
816
|
-
return
|
817
|
-
}
|
818
|
-
const element = this.getCurrentParsedomElement(parsedom, useCache)
|
819
|
-
if (element) {
|
820
|
-
element.toEmpty()
|
821
|
-
if (isRender) {
|
822
|
-
this.editor.formatElementStack()
|
823
|
-
this.editor.domRender()
|
824
|
-
this.editor.rangeRender()
|
825
|
-
}
|
826
|
-
}
|
827
|
-
},
|
828
|
-
//api:当光标在链接上时可以移除链接
|
829
|
-
removeLink(isRender = true, useCache = false) {
|
830
|
-
if (this.disabled) {
|
831
|
-
return
|
832
|
-
}
|
833
|
-
if (!this.editor.range) {
|
834
|
-
return
|
835
|
-
}
|
836
|
-
const link = this.getCurrentParsedomElement('a', useCache)
|
837
|
-
if (link) {
|
838
|
-
link.parsedom = AlexElement.TEXT_NODE
|
839
|
-
delete link.marks.target
|
840
|
-
delete link.marks.href
|
841
|
-
if (isRender) {
|
842
|
-
this.editor.formatElementStack()
|
843
|
-
this.editor.domRender()
|
844
|
-
this.editor.rangeRender()
|
845
|
-
}
|
846
|
-
}
|
847
|
-
},
|
848
|
-
//api:设置标题
|
849
|
-
setHeading(parsedom, isRender = true, useCache = false) {
|
850
|
-
if (this.disabled) {
|
851
|
-
return
|
852
|
-
}
|
853
|
-
if (!this.editor.range) {
|
854
|
-
return
|
855
|
-
}
|
856
|
-
const values = getButtonOptionsConfig(this.$editTrans, this.$editLocale).heading.map(item => {
|
857
|
-
return item.value
|
858
|
-
})
|
859
|
-
if (!values.includes(parsedom)) {
|
860
|
-
throw new Error('The parameter supports only h1-h6 and p')
|
861
|
-
}
|
862
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
863
|
-
const block = this.editor.range.anchor.element.getBlock()
|
864
|
-
//先转为段落
|
865
|
-
blockToParagraph(block)
|
866
|
-
//设置标题
|
867
|
-
block.parsedom = parsedom
|
868
|
-
} else {
|
869
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
870
|
-
result.forEach(el => {
|
871
|
-
if (el.element.isBlock()) {
|
872
|
-
blockToParagraph(el.element)
|
873
|
-
el.element.parsedom = parsedom
|
874
|
-
} else {
|
875
|
-
const block = el.element.getBlock()
|
876
|
-
blockToParagraph(block)
|
877
|
-
block.parsedom = parsedom
|
878
|
-
}
|
879
|
-
})
|
880
|
-
}
|
881
|
-
if (isRender) {
|
882
|
-
this.editor.formatElementStack()
|
883
|
-
this.editor.domRender()
|
884
|
-
this.editor.rangeRender()
|
885
|
-
}
|
886
|
-
},
|
887
|
-
//api:插入有序列表 ordered为true表示有序列表
|
888
|
-
setList(ordered, isRender = true, useCache = false) {
|
889
|
-
if (this.disabled) {
|
890
|
-
return
|
891
|
-
}
|
892
|
-
if (!this.editor.range) {
|
893
|
-
return
|
894
|
-
}
|
895
|
-
//起点和终点在一起
|
896
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
897
|
-
const block = this.editor.range.anchor.element.getBlock()
|
898
|
-
const isList = blockIsList(block, ordered)
|
899
|
-
if (isList) {
|
900
|
-
blockToParagraph(block)
|
901
|
-
} else {
|
902
|
-
blockToList(block, ordered)
|
903
|
-
}
|
904
|
-
}
|
905
|
-
//起点和终点不在一起
|
906
|
-
else {
|
907
|
-
let blocks = []
|
908
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
909
|
-
result.forEach(item => {
|
910
|
-
const block = item.element.getBlock()
|
911
|
-
const exist = blocks.some(el => block.isEqual(el))
|
912
|
-
if (!exist) {
|
913
|
-
blocks.push(block)
|
914
|
-
}
|
915
|
-
})
|
916
|
-
blocks.forEach(block => {
|
917
|
-
const isList = blockIsList(block, ordered)
|
918
|
-
if (isList) {
|
919
|
-
blockToParagraph(block)
|
920
|
-
} else {
|
921
|
-
blockToList(block, ordered)
|
922
|
-
}
|
923
|
-
})
|
924
|
-
}
|
925
|
-
if (isRender) {
|
926
|
-
this.editor.formatElementStack()
|
927
|
-
this.editor.domRender()
|
928
|
-
this.editor.rangeRender()
|
929
|
-
}
|
930
|
-
},
|
931
|
-
//api:插入任务列表
|
932
|
-
setTask(isRender = true, useCache = false) {
|
933
|
-
if (this.disabled) {
|
934
|
-
return
|
935
|
-
}
|
936
|
-
if (!this.editor.range) {
|
937
|
-
return
|
938
|
-
}
|
939
|
-
//起点和终点在一起
|
940
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
941
|
-
const block = this.editor.range.anchor.element.getBlock()
|
942
|
-
const isTask = blockIsTask(block)
|
943
|
-
if (isTask) {
|
944
|
-
blockToParagraph(block)
|
945
|
-
} else {
|
946
|
-
blockToTask(block)
|
947
|
-
}
|
948
|
-
}
|
949
|
-
//起点和终点不在一起
|
950
|
-
else {
|
951
|
-
let blocks = []
|
952
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
953
|
-
result.forEach(item => {
|
954
|
-
const block = item.element.getBlock()
|
955
|
-
const exist = blocks.some(el => block.isEqual(el))
|
956
|
-
if (!exist) {
|
957
|
-
blocks.push(block)
|
958
|
-
}
|
959
|
-
})
|
960
|
-
blocks.forEach(block => {
|
961
|
-
const isTask = blockIsTask(block)
|
962
|
-
if (isTask) {
|
963
|
-
blockToParagraph(block)
|
964
|
-
} else {
|
965
|
-
blockToTask(block)
|
966
|
-
}
|
967
|
-
})
|
968
|
-
}
|
969
|
-
if (isRender) {
|
970
|
-
this.editor.formatElementStack()
|
971
|
-
this.editor.domRender()
|
972
|
-
this.editor.rangeRender()
|
973
|
-
}
|
974
|
-
},
|
975
|
-
//api:设置样式
|
976
|
-
setTextStyle(name, value, isRender = true, useCache = false) {
|
977
|
-
if (this.disabled) {
|
978
|
-
return
|
979
|
-
}
|
980
|
-
if (!this.editor.range) {
|
981
|
-
return
|
982
|
-
}
|
983
|
-
const active = this.queryTextStyle(name, value, useCache)
|
984
|
-
if (active) {
|
985
|
-
this.editor.removeTextStyle([name], true)
|
986
|
-
} else {
|
987
|
-
let styles = {}
|
988
|
-
styles[name] = value
|
989
|
-
this.editor.setTextStyle(styles, true)
|
990
|
-
}
|
991
|
-
if (isRender) {
|
992
|
-
this.editor.formatElementStack()
|
993
|
-
this.editor.domRender()
|
994
|
-
this.editor.rangeRender()
|
995
|
-
}
|
996
|
-
},
|
997
|
-
//api:查询是否具有某个样式
|
998
|
-
queryTextStyle(name, value, useCache = false) {
|
999
|
-
return this.editor.queryTextStyle(name, value, useCache)
|
1000
|
-
},
|
1001
|
-
//api:设置标记
|
1002
|
-
setTextMark(name, value, isRender = true, useCache = false) {
|
1003
|
-
if (this.disabled) {
|
1004
|
-
return
|
1005
|
-
}
|
1006
|
-
if (!this.editor.range) {
|
1007
|
-
return
|
1008
|
-
}
|
1009
|
-
const active = this.queryTextMark(name, value, useCache)
|
1010
|
-
if (active) {
|
1011
|
-
this.editor.removeTextMark([name], true)
|
1012
|
-
} else {
|
1013
|
-
let marks = {}
|
1014
|
-
marks[name] = value
|
1015
|
-
this.editor.setTextMark(marks, true)
|
1016
|
-
}
|
1017
|
-
if (isRender) {
|
1018
|
-
this.editor.formatElementStack()
|
1019
|
-
this.editor.domRender()
|
1020
|
-
this.editor.rangeRender()
|
1021
|
-
}
|
1022
|
-
},
|
1023
|
-
//api:查询是否具有某个标记
|
1024
|
-
queryTextMark(name, value, useCache = false) {
|
1025
|
-
return this.editor.queryTextMark(name, value, useCache)
|
1026
|
-
},
|
1027
|
-
//api:清除文本样式和标记
|
1028
|
-
formatText(isRender = true, useCache = false) {
|
1029
|
-
if (this.disabled) {
|
1030
|
-
return
|
1031
|
-
}
|
1032
|
-
if (!this.editor.range) {
|
1033
|
-
return
|
1034
|
-
}
|
1035
|
-
this.editor.removeTextStyle(null, useCache)
|
1036
|
-
//这里不能使用缓存,因为removeTextStyle会更新光标位置
|
1037
|
-
this.editor.removeTextMark(null)
|
1038
|
-
if (isRender) {
|
1039
|
-
this.editor.formatElementStack()
|
1040
|
-
this.editor.domRender()
|
1041
|
-
this.editor.rangeRender()
|
1042
|
-
}
|
1043
|
-
},
|
1044
|
-
//api:设置对齐方式,参数取值justify/left/right/center
|
1045
|
-
setAlign(value, isRender = true, useCache = false) {
|
1046
|
-
if (this.disabled) {
|
1047
|
-
return
|
1048
|
-
}
|
1049
|
-
if (!this.editor.range) {
|
1050
|
-
return
|
1051
|
-
}
|
1052
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1053
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1054
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1055
|
-
if (inblock) {
|
1056
|
-
if (inblock.hasStyles()) {
|
1057
|
-
inblock.styles['text-align'] = value
|
1058
|
-
} else {
|
1059
|
-
inblock.styles = {
|
1060
|
-
'text-align': value
|
1061
|
-
}
|
1062
|
-
}
|
1063
|
-
} else {
|
1064
|
-
if (block.hasStyles()) {
|
1065
|
-
block.styles['text-align'] = value
|
1066
|
-
} else {
|
1067
|
-
block.styles = {
|
1068
|
-
'text-align': value
|
1069
|
-
}
|
1070
|
-
}
|
1071
|
-
}
|
1072
|
-
} else {
|
1073
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1074
|
-
result.forEach(el => {
|
1075
|
-
if (el.element.isBlock() || el.element.isInblock()) {
|
1076
|
-
if (el.element.hasStyles()) {
|
1077
|
-
el.element.styles['text-align'] = value
|
1078
|
-
} else {
|
1079
|
-
el.element.styles = {
|
1080
|
-
'text-align': value
|
1081
|
-
}
|
1082
|
-
}
|
1083
|
-
} else {
|
1084
|
-
const block = el.element.getBlock()
|
1085
|
-
const inblock = el.element.getInblock()
|
1086
|
-
if (inblock) {
|
1087
|
-
if (inblock.hasStyles()) {
|
1088
|
-
inblock.styles['text-align'] = value
|
1089
|
-
} else {
|
1090
|
-
inblock.styles = {
|
1091
|
-
'text-align': value
|
1092
|
-
}
|
1093
|
-
}
|
1094
|
-
} else {
|
1095
|
-
if (block.hasStyles()) {
|
1096
|
-
block.styles['text-align'] = value
|
1097
|
-
} else {
|
1098
|
-
block.styles = {
|
1099
|
-
'text-align': value
|
1100
|
-
}
|
1101
|
-
}
|
1102
|
-
}
|
1103
|
-
}
|
1104
|
-
})
|
1105
|
-
}
|
1106
|
-
if (isRender) {
|
1107
|
-
this.editor.formatElementStack()
|
1108
|
-
this.editor.domRender()
|
1109
|
-
this.editor.rangeRender()
|
1110
|
-
}
|
1111
|
-
},
|
1112
739
|
//api:撤销
|
1113
740
|
undo() {
|
1114
741
|
if (this.disabled) {
|
@@ -1138,621 +765,15 @@ export default {
|
|
1138
765
|
this.editor.domRender(true)
|
1139
766
|
this.editor.rangeRender()
|
1140
767
|
}
|
1141
|
-
},
|
1142
|
-
//api:插入引用
|
1143
|
-
setQuote(isRender = true, useCache = false) {
|
1144
|
-
if (this.disabled) {
|
1145
|
-
return
|
1146
|
-
}
|
1147
|
-
if (!this.editor.range) {
|
1148
|
-
return
|
1149
|
-
}
|
1150
|
-
//起点和终点在一起
|
1151
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1152
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1153
|
-
const oldParsedom = block.parsedom
|
1154
|
-
blockToParagraph(block)
|
1155
|
-
if (oldParsedom != 'blockquote') {
|
1156
|
-
block.parsedom = 'blockquote'
|
1157
|
-
}
|
1158
|
-
}
|
1159
|
-
//起点和终点不在一起
|
1160
|
-
else {
|
1161
|
-
let blocks = []
|
1162
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1163
|
-
result.forEach(item => {
|
1164
|
-
const block = item.element.getBlock()
|
1165
|
-
const exist = blocks.some(el => block.isEqual(el))
|
1166
|
-
if (!exist) {
|
1167
|
-
blocks.push(block)
|
1168
|
-
}
|
1169
|
-
})
|
1170
|
-
blocks.forEach(block => {
|
1171
|
-
const oldParsedom = block.parsedom
|
1172
|
-
blockToParagraph(block)
|
1173
|
-
if (oldParsedom != 'blockquote') {
|
1174
|
-
block.parsedom = 'blockquote'
|
1175
|
-
}
|
1176
|
-
})
|
1177
|
-
}
|
1178
|
-
if (isRender) {
|
1179
|
-
this.editor.formatElementStack()
|
1180
|
-
this.editor.domRender()
|
1181
|
-
this.editor.rangeRender()
|
1182
|
-
}
|
1183
|
-
},
|
1184
|
-
//api:设置行高
|
1185
|
-
setLineHeight(value, isRender = true, useCache = false) {
|
1186
|
-
if (this.disabled) {
|
1187
|
-
return
|
1188
|
-
}
|
1189
|
-
if (!this.editor.range) {
|
1190
|
-
return
|
1191
|
-
}
|
1192
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1193
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1194
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1195
|
-
if (inblock) {
|
1196
|
-
if (inblock.hasStyles()) {
|
1197
|
-
inblock.styles['line-height'] = value
|
1198
|
-
} else {
|
1199
|
-
inblock.styles = {
|
1200
|
-
'line-height': value
|
1201
|
-
}
|
1202
|
-
}
|
1203
|
-
} else {
|
1204
|
-
if (block.hasStyles()) {
|
1205
|
-
block.styles['line-height'] = value
|
1206
|
-
} else {
|
1207
|
-
block.styles = {
|
1208
|
-
'line-height': value
|
1209
|
-
}
|
1210
|
-
}
|
1211
|
-
}
|
1212
|
-
} else {
|
1213
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1214
|
-
result.forEach(el => {
|
1215
|
-
if (el.element.isBlock() || el.element.isInblock()) {
|
1216
|
-
if (el.element.hasStyles()) {
|
1217
|
-
el.element.styles['line-height'] = value
|
1218
|
-
} else {
|
1219
|
-
el.element.styles = {
|
1220
|
-
'line-height': value
|
1221
|
-
}
|
1222
|
-
}
|
1223
|
-
} else {
|
1224
|
-
const block = el.element.getBlock()
|
1225
|
-
const inblock = el.element.getInblock()
|
1226
|
-
if (inblock) {
|
1227
|
-
if (inblock.hasStyles()) {
|
1228
|
-
inblock.styles['line-height'] = value
|
1229
|
-
} else {
|
1230
|
-
inblock.styles = {
|
1231
|
-
'line-height': value
|
1232
|
-
}
|
1233
|
-
}
|
1234
|
-
} else {
|
1235
|
-
if (block.hasStyles()) {
|
1236
|
-
block.styles['line-height'] = value
|
1237
|
-
} else {
|
1238
|
-
block.styles = {
|
1239
|
-
'line-height': value
|
1240
|
-
}
|
1241
|
-
}
|
1242
|
-
}
|
1243
|
-
}
|
1244
|
-
})
|
1245
|
-
}
|
1246
|
-
if (isRender) {
|
1247
|
-
this.editor.formatElementStack()
|
1248
|
-
this.editor.domRender()
|
1249
|
-
this.editor.rangeRender()
|
1250
|
-
}
|
1251
|
-
},
|
1252
|
-
//api:增加缩进
|
1253
|
-
setIndentIncrease(isRender = true, useCache = false) {
|
1254
|
-
if (this.disabled) {
|
1255
|
-
return
|
1256
|
-
}
|
1257
|
-
if (!this.editor.range) {
|
1258
|
-
return
|
1259
|
-
}
|
1260
|
-
const fn = element => {
|
1261
|
-
if (element.hasStyles()) {
|
1262
|
-
if (element.styles.hasOwnProperty('text-indent')) {
|
1263
|
-
let val = element.styles['text-indent']
|
1264
|
-
if (val.endsWith('em')) {
|
1265
|
-
val = parseFloat(val)
|
1266
|
-
} else {
|
1267
|
-
val = 0
|
1268
|
-
}
|
1269
|
-
element.styles['text-indent'] = `${val + 2}em`
|
1270
|
-
} else {
|
1271
|
-
element.styles['text-indent'] = '2em'
|
1272
|
-
}
|
1273
|
-
} else {
|
1274
|
-
element.styles = {
|
1275
|
-
'text-indent': '2em'
|
1276
|
-
}
|
1277
|
-
}
|
1278
|
-
}
|
1279
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1280
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1281
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1282
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1283
|
-
fn(inblock)
|
1284
|
-
} else if (!block.isPreStyle()) {
|
1285
|
-
fn(block)
|
1286
|
-
}
|
1287
|
-
} else {
|
1288
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1289
|
-
result.forEach(item => {
|
1290
|
-
const block = item.element.getBlock()
|
1291
|
-
const inblock = item.element.getInblock()
|
1292
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1293
|
-
fn(inblock)
|
1294
|
-
} else if (!block.isPreStyle()) {
|
1295
|
-
fn(block)
|
1296
|
-
}
|
1297
|
-
})
|
1298
|
-
}
|
1299
|
-
if (isRender) {
|
1300
|
-
this.editor.formatElementStack()
|
1301
|
-
this.editor.domRender()
|
1302
|
-
this.editor.rangeRender()
|
1303
|
-
}
|
1304
|
-
},
|
1305
|
-
//api:减少缩进
|
1306
|
-
setIndentDecrease(isRender = true, useCache = false) {
|
1307
|
-
if (this.disabled) {
|
1308
|
-
return
|
1309
|
-
}
|
1310
|
-
if (!this.editor.range) {
|
1311
|
-
return
|
1312
|
-
}
|
1313
|
-
const fn = element => {
|
1314
|
-
if (element.hasStyles() && element.styles.hasOwnProperty('text-indent')) {
|
1315
|
-
let val = element.styles['text-indent']
|
1316
|
-
if (val.endsWith('em')) {
|
1317
|
-
val = parseFloat(val)
|
1318
|
-
} else {
|
1319
|
-
val = 0
|
1320
|
-
}
|
1321
|
-
element.styles['text-indent'] = `${val - 2 >= 0 ? val - 2 : 0}em`
|
1322
|
-
}
|
1323
|
-
}
|
1324
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1325
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1326
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1327
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1328
|
-
fn(inblock)
|
1329
|
-
} else if (!block.isPreStyle()) {
|
1330
|
-
fn(block)
|
1331
|
-
}
|
1332
|
-
} else {
|
1333
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1334
|
-
result.forEach(item => {
|
1335
|
-
const block = item.element.getBlock()
|
1336
|
-
const inblock = item.element.getInblock()
|
1337
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1338
|
-
fn(inblock)
|
1339
|
-
} else if (!block.isPreStyle()) {
|
1340
|
-
fn(block)
|
1341
|
-
}
|
1342
|
-
})
|
1343
|
-
}
|
1344
|
-
if (isRender) {
|
1345
|
-
this.editor.formatElementStack()
|
1346
|
-
this.editor.domRender()
|
1347
|
-
this.editor.rangeRender()
|
1348
|
-
}
|
1349
|
-
},
|
1350
|
-
//api:插入图片
|
1351
|
-
insertImage(url, isRender = true, useCache = false) {
|
1352
|
-
if (this.disabled) {
|
1353
|
-
return
|
1354
|
-
}
|
1355
|
-
if (!this.editor.range) {
|
1356
|
-
return
|
1357
|
-
}
|
1358
|
-
if (!url || typeof url != 'string') {
|
1359
|
-
throw new Error('An image address must be given')
|
1360
|
-
}
|
1361
|
-
const image = new AlexElement(
|
1362
|
-
'closed',
|
1363
|
-
'img',
|
1364
|
-
{
|
1365
|
-
src: url
|
1366
|
-
},
|
1367
|
-
null,
|
1368
|
-
null
|
1369
|
-
)
|
1370
|
-
this.editor.insertElement(image, true, useCache)
|
1371
|
-
if (isRender) {
|
1372
|
-
this.editor.formatElementStack()
|
1373
|
-
this.editor.domRender()
|
1374
|
-
this.editor.rangeRender()
|
1375
|
-
}
|
1376
|
-
},
|
1377
|
-
//api:插入视频
|
1378
|
-
insertVideo(url, isRender = true, useCache = false) {
|
1379
|
-
if (this.disabled) {
|
1380
|
-
return
|
1381
|
-
}
|
1382
|
-
if (!this.editor.range) {
|
1383
|
-
return
|
1384
|
-
}
|
1385
|
-
if (!url || typeof url != 'string') {
|
1386
|
-
throw new Error('A video address must be given')
|
1387
|
-
}
|
1388
|
-
const video = new AlexElement(
|
1389
|
-
'closed',
|
1390
|
-
'video',
|
1391
|
-
{
|
1392
|
-
src: url
|
1393
|
-
},
|
1394
|
-
null,
|
1395
|
-
null
|
1396
|
-
)
|
1397
|
-
this.editor.insertElement(video, true, useCache)
|
1398
|
-
const leftSpace = AlexElement.getSpaceElement()
|
1399
|
-
const rightSpace = AlexElement.getSpaceElement()
|
1400
|
-
this.editor.addElementAfter(rightSpace, video)
|
1401
|
-
this.editor.addElementBefore(leftSpace, video)
|
1402
|
-
this.editor.range.anchor.moveToEnd(rightSpace)
|
1403
|
-
this.editor.range.focus.moveToEnd(rightSpace)
|
1404
|
-
if (isRender) {
|
1405
|
-
this.editor.formatElementStack()
|
1406
|
-
this.editor.domRender()
|
1407
|
-
this.editor.rangeRender()
|
1408
|
-
}
|
1409
|
-
},
|
1410
|
-
//api:选区是否含有代码块样式
|
1411
|
-
hasPreStyle(useCache = false) {
|
1412
|
-
if (!this.editor.range) {
|
1413
|
-
return false
|
1414
|
-
}
|
1415
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1416
|
-
return this.editor.range.anchor.element.isPreStyle()
|
1417
|
-
}
|
1418
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1419
|
-
return result.some(item => {
|
1420
|
-
return item.element.isPreStyle()
|
1421
|
-
})
|
1422
|
-
},
|
1423
|
-
//api:选区是否含有引用
|
1424
|
-
hasQuote(useCache = false) {
|
1425
|
-
if (!this.editor.range) {
|
1426
|
-
return false
|
1427
|
-
}
|
1428
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1429
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1430
|
-
return block.parsedom == 'blockquote'
|
1431
|
-
}
|
1432
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1433
|
-
return result.some(item => {
|
1434
|
-
if (item.element.isBlock()) {
|
1435
|
-
return item.element.parsedom == 'blockquote'
|
1436
|
-
} else {
|
1437
|
-
const block = item.element.getBlock()
|
1438
|
-
return block.parsedom == 'blockquote'
|
1439
|
-
}
|
1440
|
-
})
|
1441
|
-
},
|
1442
|
-
//api:选区是否含有列表
|
1443
|
-
hasList(ordered = false, useCache = false) {
|
1444
|
-
if (!this.editor.range) {
|
1445
|
-
return false
|
1446
|
-
}
|
1447
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1448
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1449
|
-
return blockIsList(block, ordered)
|
1450
|
-
}
|
1451
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1452
|
-
return result.some(item => {
|
1453
|
-
if (item.element.isBlock()) {
|
1454
|
-
return blockIsList(item.element, ordered)
|
1455
|
-
} else {
|
1456
|
-
const block = item.element.getBlock()
|
1457
|
-
return blockIsList(block, ordered)
|
1458
|
-
}
|
1459
|
-
})
|
1460
|
-
},
|
1461
|
-
//api:选区是否含有链接
|
1462
|
-
hasLink(useCache = false) {
|
1463
|
-
if (!this.editor.range) {
|
1464
|
-
return false
|
1465
|
-
}
|
1466
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1467
|
-
return !!this.getParsedomElementByElement(this.editor.range.anchor.element, 'a')
|
1468
|
-
}
|
1469
|
-
const result = this.editor.getElementsByRange(useCache).flatIncludes.filter(item => {
|
1470
|
-
return item.element.isText()
|
1471
|
-
})
|
1472
|
-
return result.some(item => {
|
1473
|
-
return !!this.getParsedomElementByElement(item.element, 'a')
|
1474
|
-
})
|
1475
|
-
},
|
1476
|
-
//api:选区是否含有表格
|
1477
|
-
hasTable(useCache = false) {
|
1478
|
-
if (!this.editor.range) {
|
1479
|
-
return false
|
1480
|
-
}
|
1481
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1482
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1483
|
-
return block.parsedom == 'table'
|
1484
|
-
}
|
1485
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1486
|
-
return result.some(item => {
|
1487
|
-
if (item.element.isBlock()) {
|
1488
|
-
return item.element.parsedom == 'table'
|
1489
|
-
} else {
|
1490
|
-
const block = item.element.getBlock()
|
1491
|
-
return block.parsedom == 'table'
|
1492
|
-
}
|
1493
|
-
})
|
1494
|
-
},
|
1495
|
-
//api:选区是否含有任务列表
|
1496
|
-
hasTask(useCache = false) {
|
1497
|
-
if (!this.editor.range) {
|
1498
|
-
return false
|
1499
|
-
}
|
1500
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1501
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1502
|
-
return blockIsTask(block)
|
1503
|
-
}
|
1504
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1505
|
-
return result.some(item => {
|
1506
|
-
if (item.element.isBlock()) {
|
1507
|
-
return blockIsTask(item.element)
|
1508
|
-
} else {
|
1509
|
-
const block = item.element.getBlock()
|
1510
|
-
return blockIsTask(block)
|
1511
|
-
}
|
1512
|
-
})
|
1513
|
-
},
|
1514
|
-
//api:选区是否含有图片
|
1515
|
-
hasImage(useCache = false) {
|
1516
|
-
if (!this.editor.range) {
|
1517
|
-
return false
|
1518
|
-
}
|
1519
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1520
|
-
return this.editor.range.anchor.element.isClosed() && this.editor.range.anchor.element.parsedom == 'img'
|
1521
|
-
}
|
1522
|
-
const result = this.editor.getElementsByRange(useCache).flatIncludes
|
1523
|
-
return result.some(item => {
|
1524
|
-
return item.element.isClosed() && item.element.parsedom == 'img'
|
1525
|
-
})
|
1526
|
-
},
|
1527
|
-
//api:选区是否含有视频
|
1528
|
-
hasVideo(useCache = false) {
|
1529
|
-
if (!this.editor.range) {
|
1530
|
-
return false
|
1531
|
-
}
|
1532
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1533
|
-
return this.editor.range.anchor.element.isClosed() && this.editor.range.anchor.element.parsedom == 'video'
|
1534
|
-
}
|
1535
|
-
const result = this.editor.getElementsByRange(useCache).flatIncludes
|
1536
|
-
return result.some(item => {
|
1537
|
-
return item.element.isClosed() && item.element.parsedom == 'video'
|
1538
|
-
})
|
1539
|
-
},
|
1540
|
-
//api:选区是否全部在引用内
|
1541
|
-
inQuote(useCache = false) {
|
1542
|
-
if (!this.editor.range) {
|
1543
|
-
return false
|
1544
|
-
}
|
1545
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1546
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1547
|
-
return block.parsedom == 'blockquote'
|
1548
|
-
}
|
1549
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1550
|
-
return result.every(item => {
|
1551
|
-
if (item.element.isBlock()) {
|
1552
|
-
return item.element.parsedom == 'blockquote'
|
1553
|
-
} else {
|
1554
|
-
const block = item.element.getBlock()
|
1555
|
-
return block.parsedom == 'blockquote'
|
1556
|
-
}
|
1557
|
-
})
|
1558
|
-
},
|
1559
|
-
//api:选区是否全部在列表内
|
1560
|
-
inList(ordered = false, useCache = false) {
|
1561
|
-
if (!this.editor.range) {
|
1562
|
-
return false
|
1563
|
-
}
|
1564
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1565
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1566
|
-
return blockIsList(block, ordered)
|
1567
|
-
}
|
1568
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1569
|
-
return result.every(item => {
|
1570
|
-
if (item.element.isBlock()) {
|
1571
|
-
return blockIsList(item.element, ordered)
|
1572
|
-
} else {
|
1573
|
-
const block = item.element.getBlock()
|
1574
|
-
return blockIsList(block, ordered)
|
1575
|
-
}
|
1576
|
-
})
|
1577
|
-
},
|
1578
|
-
//api:选区是否全部在任务列表里
|
1579
|
-
inTask(useCache = false) {
|
1580
|
-
if (!this.editor.range) {
|
1581
|
-
return false
|
1582
|
-
}
|
1583
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1584
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1585
|
-
return blockIsTask(block)
|
1586
|
-
}
|
1587
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1588
|
-
return result.every(item => {
|
1589
|
-
if (item.element.isBlock()) {
|
1590
|
-
return blockIsTask(item.element)
|
1591
|
-
} else {
|
1592
|
-
const block = item.element.getBlock()
|
1593
|
-
return blockIsTask(block)
|
1594
|
-
}
|
1595
|
-
})
|
1596
|
-
},
|
1597
|
-
//api:创建一个空的表格
|
1598
|
-
insertTable(rowLength, colLength, isRender = true, useCache = false) {
|
1599
|
-
if (this.disabled) {
|
1600
|
-
return
|
1601
|
-
}
|
1602
|
-
if (!this.editor.range) {
|
1603
|
-
return
|
1604
|
-
}
|
1605
|
-
const table = new AlexElement('block', 'table', null, null, null)
|
1606
|
-
const tbody = new AlexElement('inblock', 'tbody', null, null, null)
|
1607
|
-
this.editor.addElementTo(tbody, table)
|
1608
|
-
for (let i = 0; i < rowLength; i++) {
|
1609
|
-
const row = new AlexElement('inblock', 'tr', null, null, null)
|
1610
|
-
for (let j = 0; j < colLength; j++) {
|
1611
|
-
const column = new AlexElement('inblock', 'td', null, null, null)
|
1612
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1613
|
-
this.editor.addElementTo(breakEl, column)
|
1614
|
-
this.editor.addElementTo(column, row)
|
1615
|
-
}
|
1616
|
-
this.editor.addElementTo(row, tbody)
|
1617
|
-
}
|
1618
|
-
this.editor.insertElement(table, true, useCache)
|
1619
|
-
//在表格后创建一个段落
|
1620
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1621
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1622
|
-
this.editor.addElementTo(breakEl, paragraph)
|
1623
|
-
this.editor.addElementAfter(paragraph, table)
|
1624
|
-
this.editor.range.anchor.moveToStart(tbody)
|
1625
|
-
this.editor.range.focus.moveToStart(tbody)
|
1626
|
-
if (isRender) {
|
1627
|
-
this.editor.formatElementStack()
|
1628
|
-
this.editor.domRender()
|
1629
|
-
this.editor.rangeRender()
|
1630
|
-
}
|
1631
|
-
},
|
1632
|
-
//api:插入代码块
|
1633
|
-
insertCodeBlock(isRender = true, useCache = false) {
|
1634
|
-
if (this.disabled) {
|
1635
|
-
return
|
1636
|
-
}
|
1637
|
-
if (!this.editor.range) {
|
1638
|
-
return
|
1639
|
-
}
|
1640
|
-
const pre = this.getCurrentParsedomElement('pre', useCache)
|
1641
|
-
if (pre) {
|
1642
|
-
let content = ''
|
1643
|
-
AlexElement.flatElements(pre.children)
|
1644
|
-
.filter(item => {
|
1645
|
-
return item.isText()
|
1646
|
-
})
|
1647
|
-
.forEach(item => {
|
1648
|
-
content += item.textContent
|
1649
|
-
})
|
1650
|
-
const splits = content.split('\n')
|
1651
|
-
splits.forEach(item => {
|
1652
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1653
|
-
const text = new AlexElement('text', null, null, null, item)
|
1654
|
-
this.editor.addElementTo(text, paragraph)
|
1655
|
-
this.editor.addElementBefore(paragraph, pre)
|
1656
|
-
})
|
1657
|
-
pre.toEmpty()
|
1658
|
-
} else {
|
1659
|
-
//起点和终点在一起
|
1660
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1661
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1662
|
-
blockToParagraph(block)
|
1663
|
-
block.parsedom = 'pre'
|
1664
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1665
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1666
|
-
this.editor.addElementTo(breakEl, paragraph)
|
1667
|
-
this.editor.addElementAfter(paragraph, block)
|
1668
|
-
}
|
1669
|
-
//起点和终点不在一起
|
1670
|
-
else {
|
1671
|
-
let result = this.editor.getElementsByRange(true).includes
|
1672
|
-
this.editor.range.anchor.moveToStart(result[0].element.getBlock())
|
1673
|
-
this.editor.range.focus.moveToEnd(result[result.length - 1].element.getBlock())
|
1674
|
-
const res = this.editor.getElementsByRange(true).flatIncludes.filter(el => el.element.isText())
|
1675
|
-
const obj = {}
|
1676
|
-
res.forEach(el => {
|
1677
|
-
if (obj[el.element.getBlock().key]) {
|
1678
|
-
obj[el.element.getBlock().key].push(el.element.clone())
|
1679
|
-
} else {
|
1680
|
-
obj[el.element.getBlock().key] = [el.element.clone()]
|
1681
|
-
}
|
1682
|
-
})
|
1683
|
-
const pre = new AlexElement('block', 'pre', null, null, null)
|
1684
|
-
Object.keys(obj).forEach((key, index) => {
|
1685
|
-
if (index > 0) {
|
1686
|
-
const text = new AlexElement('text', null, null, null, '\n')
|
1687
|
-
if (pre.hasChildren()) {
|
1688
|
-
this.editor.addElementTo(text, pre, pre.children.length)
|
1689
|
-
} else {
|
1690
|
-
this.editor.addElementTo(text, pre)
|
1691
|
-
}
|
1692
|
-
}
|
1693
|
-
obj[key].forEach(el => {
|
1694
|
-
if (pre.hasChildren()) {
|
1695
|
-
this.editor.addElementTo(el, pre, pre.children.length)
|
1696
|
-
} else {
|
1697
|
-
this.editor.addElementTo(el, pre)
|
1698
|
-
}
|
1699
|
-
})
|
1700
|
-
})
|
1701
|
-
this.editor.delete()
|
1702
|
-
this.editor.insertElement(pre)
|
1703
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1704
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1705
|
-
this.editor.addElementTo(breakEl, paragraph)
|
1706
|
-
this.editor.addElementAfter(paragraph, pre)
|
1707
|
-
}
|
1708
|
-
}
|
1709
|
-
if (isRender) {
|
1710
|
-
this.editor.formatElementStack()
|
1711
|
-
this.editor.domRender()
|
1712
|
-
this.editor.rangeRender()
|
1713
|
-
}
|
1714
|
-
},
|
1715
|
-
//api:插入文本
|
1716
|
-
insertText(text, isRender = true, useCache = false) {
|
1717
|
-
if (this.disabled) {
|
1718
|
-
return
|
1719
|
-
}
|
1720
|
-
if (!this.editor.range) {
|
1721
|
-
return
|
1722
|
-
}
|
1723
|
-
this.editor.insertText(text, useCache)
|
1724
|
-
if (isRender) {
|
1725
|
-
this.editor.formatElementStack()
|
1726
|
-
this.editor.domRender()
|
1727
|
-
this.editor.rangeRender()
|
1728
|
-
}
|
1729
|
-
},
|
1730
|
-
//api:插入html
|
1731
|
-
insertHtml(html, isRender = true, useCache = false) {
|
1732
|
-
if (this.disabled) {
|
1733
|
-
return
|
1734
|
-
}
|
1735
|
-
if (!this.editor.range) {
|
1736
|
-
return
|
1737
|
-
}
|
1738
|
-
const elements = this.editor.parseHtml(html)
|
1739
|
-
for (let i = 0; i < elements.length; i++) {
|
1740
|
-
this.editor.insertElement(elements[i], false, i == 0 ? useCache : false)
|
1741
|
-
}
|
1742
|
-
if (isRender) {
|
1743
|
-
this.editor.formatElementStack()
|
1744
|
-
this.editor.domRender()
|
1745
|
-
this.editor.rangeRender()
|
1746
|
-
}
|
1747
768
|
}
|
1748
769
|
},
|
1749
770
|
beforeUnmount() {
|
1750
771
|
//卸载绑定在滚动元素上的事件
|
1751
772
|
this.removeScrollHandle()
|
1752
773
|
//卸载绑定在document.documentElement上的事件
|
1753
|
-
|
774
|
+
DapEvent.off(document.documentElement, `mousedown.editify_${this.uid} mousemove.editify_${this.uid} mouseup.editify_${this.uid} click.editify_${this.uid}`)
|
1754
775
|
//卸载绑定在window上的事件
|
1755
|
-
|
776
|
+
DapEvent.off(window, `resize.editify_${this.uid}`)
|
1756
777
|
//销毁编辑器
|
1757
778
|
this.editor.destroy()
|
1758
779
|
}
|
@@ -1760,8 +781,11 @@ export default {
|
|
1760
781
|
</script>
|
1761
782
|
<style lang="less" scoped>
|
1762
783
|
.editify {
|
1763
|
-
display:
|
784
|
+
display: flex;
|
785
|
+
justify-content: flex-start;
|
786
|
+
flex-direction: column;
|
1764
787
|
width: 100%;
|
788
|
+
height: 100%;
|
1765
789
|
position: relative;
|
1766
790
|
box-sizing: border-box;
|
1767
791
|
-webkit-tap-highlight-color: transparent;
|
@@ -1776,18 +800,14 @@ export default {
|
|
1776
800
|
-webkit-tap-highlight-color: transparent;
|
1777
801
|
outline: none;
|
1778
802
|
}
|
1779
|
-
|
1780
|
-
&.fullheight {
|
1781
|
-
height: 100%;
|
1782
|
-
}
|
1783
|
-
|
1784
803
|
&.fullscreen {
|
1785
804
|
position: fixed;
|
1786
805
|
z-index: 1000;
|
1787
806
|
left: 0;
|
1788
807
|
top: 0;
|
1789
|
-
width: 100vw;
|
1790
|
-
height: 100vh;
|
808
|
+
width: 100vw !important;
|
809
|
+
height: 100vh !important;
|
810
|
+
background: @background;
|
1791
811
|
|
1792
812
|
.editify-body {
|
1793
813
|
border-radius: 0;
|
@@ -1798,6 +818,8 @@ export default {
|
|
1798
818
|
.editify-body {
|
1799
819
|
display: block;
|
1800
820
|
width: 100%;
|
821
|
+
height: 0;
|
822
|
+
flex: 1;
|
1801
823
|
position: relative;
|
1802
824
|
background-color: @background;
|
1803
825
|
padding: 1px;
|
@@ -1829,6 +851,7 @@ export default {
|
|
1829
851
|
overflow-x: hidden;
|
1830
852
|
overflow-y: auto;
|
1831
853
|
width: 100%;
|
854
|
+
height: 100%;
|
1832
855
|
border-radius: inherit;
|
1833
856
|
padding: 6px 10px;
|
1834
857
|
line-height: 1.5;
|
@@ -2056,8 +1079,7 @@ export default {
|
|
2056
1079
|
content: '';
|
2057
1080
|
position: absolute;
|
2058
1081
|
left: 0;
|
2059
|
-
top:
|
2060
|
-
transform: translateY(-50%);
|
1082
|
+
top: 2px;
|
2061
1083
|
z-index: 1;
|
2062
1084
|
cursor: pointer;
|
2063
1085
|
}
|