vue-editify 0.1.3 → 0.1.4
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 +3 -3
- package/examples/App.vue +5668 -5669
- package/examples/main.js +4 -4
- package/lib/editify.es.js +167 -192
- package/lib/editify.umd.js +1 -1
- package/lib/style.css +1 -1
- package/package.json +37 -37
- package/src/Editify.vue +1188 -1178
- package/src/components/Menu.vue +1623 -1623
- package/src/components/Toolbar.vue +1214 -1214
- package/src/components/base/Button.vue +450 -450
- package/src/components/base/Checkbox.vue +196 -196
- package/src/components/base/Icon.vue +31 -31
- package/src/components/base/Layer.vue +712 -712
- package/src/components/base/Tooltip.vue +82 -82
- package/src/components/base/Triangle.vue +159 -159
- package/src/components/common/Colors.vue +138 -138
- package/src/components/common/InsertImage.vue +316 -316
- package/src/components/common/InsertLink.vue +136 -136
- package/src/components/common/InsertTable.vue +157 -157
- package/src/components/common/InsertVideo.vue +316 -316
- package/src/core/function.js +1044 -1044
- package/src/core/rule.js +239 -239
- package/src/core/tool.js +1056 -1051
- package/src/css/base.less +30 -30
- package/src/css/hljs.less +54 -54
- package/src/hljs/index.js +62 -62
- package/src/icon/iconfont.css +219 -219
- package/src/index.js +24 -24
- package/src/locale/en_US.js +86 -86
- package/src/locale/index.js +14 -14
- package/src/locale/zh_CN.js +86 -86
package/src/core/function.js
CHANGED
@@ -1,1044 +1,1044 @@
|
|
1
|
-
/**
|
2
|
-
* 这里的方法都是对编辑器内容元素进行判断或者操作的方法,不涉及到格式化、dom渲染和光标渲染
|
3
|
-
*/
|
4
|
-
import { AlexElement } from 'alex-editor'
|
5
|
-
import { common as DapCommon } from 'dap-util'
|
6
|
-
import { cloneData, queryHasValue, getButtonOptionsConfig } from './tool'
|
7
|
-
|
8
|
-
//判断元素是否在某个标签下,如果是返回该标签对应的元素,否则返回null
|
9
|
-
export const getParsedomElementByElement = (element, parsedom) => {
|
10
|
-
if (element.isBlock()) {
|
11
|
-
return element.parsedom == parsedom ? element : null
|
12
|
-
}
|
13
|
-
if (!element.isText() && element.parsedom == parsedom) {
|
14
|
-
return element
|
15
|
-
}
|
16
|
-
return getParsedomElementByElement(element.parent, parsedom)
|
17
|
-
}
|
18
|
-
|
19
|
-
//获取光标是否在指定标签下,如果是返回该标签对应的元素,否则返回null
|
20
|
-
export const getCurrentParsedomElement = (vm, parsedom) => {
|
21
|
-
if (vm.editor.range.anchor.element.isEqual(vm.editor.range.focus.element)) {
|
22
|
-
return getParsedomElementByElement(vm.editor.range.anchor.element, parsedom)
|
23
|
-
}
|
24
|
-
const arr = vm.dataRangeCaches.list.map(item => {
|
25
|
-
return getParsedomElementByElement(item.element, parsedom)
|
26
|
-
})
|
27
|
-
let hasNull = arr.some(el => {
|
28
|
-
return el == null
|
29
|
-
})
|
30
|
-
//如果存在null,则表示有的选区元素不在指定标签下,返回null
|
31
|
-
if (hasNull) {
|
32
|
-
return null
|
33
|
-
}
|
34
|
-
//如果只有一个元素,则返回该元素
|
35
|
-
if (arr.length == 1) {
|
36
|
-
return arr[0]
|
37
|
-
}
|
38
|
-
//默认数组中的元素都相等
|
39
|
-
let flag = true
|
40
|
-
for (let i = 1; i < arr.length; i++) {
|
41
|
-
if (!arr[i].isEqual(arr[0])) {
|
42
|
-
flag = false
|
43
|
-
break
|
44
|
-
}
|
45
|
-
}
|
46
|
-
//如果相等,则返回该元素
|
47
|
-
if (flag) {
|
48
|
-
return arr[0]
|
49
|
-
}
|
50
|
-
return null
|
51
|
-
}
|
52
|
-
|
53
|
-
//判断元素是否在有序列表或者无序列表下
|
54
|
-
export const elementIsInList = (element, ordered) => {
|
55
|
-
if (isList(element, ordered)) {
|
56
|
-
return true
|
57
|
-
}
|
58
|
-
if (element.parent) {
|
59
|
-
return elementIsInList(element.parent, ordered)
|
60
|
-
}
|
61
|
-
return false
|
62
|
-
}
|
63
|
-
|
64
|
-
//判断元素是否在任务列表下
|
65
|
-
export const elementIsInTask = element => {
|
66
|
-
if (isTask(element)) {
|
67
|
-
return true
|
68
|
-
}
|
69
|
-
if (element.parent) {
|
70
|
-
return elementIsInTask(element.parent)
|
71
|
-
}
|
72
|
-
return false
|
73
|
-
}
|
74
|
-
|
75
|
-
//判断元素是否有序或者无序列表
|
76
|
-
export const isList = function (element, ordered = false) {
|
77
|
-
return element.parsedom == 'div' && element.hasMarks() && element.marks['data-editify-list'] == (ordered ? 'ol' : 'ul')
|
78
|
-
}
|
79
|
-
|
80
|
-
//判断元素是否任务列表
|
81
|
-
export const isTask = function (element) {
|
82
|
-
return element.parsedom == 'div' && element.hasMarks() && element.marks.hasOwnProperty('data-editify-task')
|
83
|
-
}
|
84
|
-
|
85
|
-
//选区是否含有代码块
|
86
|
-
export const hasPreInRange = vm => {
|
87
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
88
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'pre')
|
89
|
-
}
|
90
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
91
|
-
return !!getParsedomElementByElement(item.element, 'pre')
|
92
|
-
})
|
93
|
-
}
|
94
|
-
|
95
|
-
//选区是否全部在代码块内
|
96
|
-
export const isRangeInPre = vm => {
|
97
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
98
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'pre')
|
99
|
-
}
|
100
|
-
return vm.dataRangeCaches.list.every(item => {
|
101
|
-
return !!getParsedomElementByElement(item.element, 'pre')
|
102
|
-
})
|
103
|
-
}
|
104
|
-
|
105
|
-
//选区是否含有引用
|
106
|
-
export const hasQuoteInRange = vm => {
|
107
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
108
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'blockquote')
|
109
|
-
}
|
110
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
111
|
-
return !!getParsedomElementByElement(item.element, 'blockquote')
|
112
|
-
})
|
113
|
-
}
|
114
|
-
|
115
|
-
//选区是否全部在引用内
|
116
|
-
export const isRangeInQuote = vm => {
|
117
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
118
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'blockquote')
|
119
|
-
}
|
120
|
-
return vm.dataRangeCaches.list.every(item => {
|
121
|
-
return !!getParsedomElementByElement(item.element, 'blockquote')
|
122
|
-
})
|
123
|
-
}
|
124
|
-
|
125
|
-
//选区是否含有有序列表或者无序列表
|
126
|
-
export const hasListInRange = (vm, ordered = false) => {
|
127
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
128
|
-
return elementIsInList(vm.editor.range.anchor.element, ordered)
|
129
|
-
}
|
130
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
131
|
-
return elementIsInList(item.element, ordered)
|
132
|
-
})
|
133
|
-
}
|
134
|
-
|
135
|
-
//选区是否全部在有序列表或者无序列表内
|
136
|
-
export const isRangeInList = (vm, ordered = false) => {
|
137
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
138
|
-
return elementIsInList(vm.editor.range.anchor.element, ordered)
|
139
|
-
}
|
140
|
-
return vm.dataRangeCaches.list.every(item => {
|
141
|
-
return elementIsInList(item.element, ordered)
|
142
|
-
})
|
143
|
-
}
|
144
|
-
|
145
|
-
//选区是否含有任务列表
|
146
|
-
export const hasTaskInRange = vm => {
|
147
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
148
|
-
return elementIsInTask(vm.editor.range.anchor.element)
|
149
|
-
}
|
150
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
151
|
-
return elementIsInTask(item.element)
|
152
|
-
})
|
153
|
-
}
|
154
|
-
|
155
|
-
//选区是否全部在任务列表里
|
156
|
-
export const isRangeInTask = vm => {
|
157
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
158
|
-
return elementIsInTask(vm.editor.range.anchor.element)
|
159
|
-
}
|
160
|
-
return vm.dataRangeCaches.list.every(item => {
|
161
|
-
return elementIsInTask(item.element)
|
162
|
-
})
|
163
|
-
}
|
164
|
-
|
165
|
-
//选区是否含有链接
|
166
|
-
export const hasLinkInRange = vm => {
|
167
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
168
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'a')
|
169
|
-
}
|
170
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
171
|
-
return !!getParsedomElementByElement(item.element, 'a')
|
172
|
-
})
|
173
|
-
}
|
174
|
-
|
175
|
-
//选区是否含有表格
|
176
|
-
export const hasTableInRange = vm => {
|
177
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
178
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'table')
|
179
|
-
}
|
180
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
181
|
-
return !!getParsedomElementByElement(item.element, 'table')
|
182
|
-
})
|
183
|
-
}
|
184
|
-
|
185
|
-
//选区是否含有图片
|
186
|
-
export const hasImageInRange = vm => {
|
187
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
188
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'img')
|
189
|
-
}
|
190
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
191
|
-
return !!getParsedomElementByElement(item.element, 'img')
|
192
|
-
})
|
193
|
-
}
|
194
|
-
|
195
|
-
//选区是否含有视频
|
196
|
-
export const hasVideoInRange = vm => {
|
197
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
198
|
-
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'video')
|
199
|
-
}
|
200
|
-
return vm.dataRangeCaches.flatList.some(item => {
|
201
|
-
return !!getParsedomElementByElement(item.element, 'video')
|
202
|
-
})
|
203
|
-
}
|
204
|
-
|
205
|
-
//查询文本元素是否具有某个样式
|
206
|
-
export const queryTextStyle = (vm, name, value) => {
|
207
|
-
//起点和终点在一起
|
208
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
209
|
-
//如果是文本元素并且具有样式
|
210
|
-
if (vm.editor.range.anchor.element.isText() && vm.editor.range.anchor.element.hasStyles()) {
|
211
|
-
return queryHasValue(vm.editor.range.anchor.element.styles, name, value)
|
212
|
-
}
|
213
|
-
//不是文本元素或者没有样式直接返回
|
214
|
-
return false
|
215
|
-
}
|
216
|
-
//起点和终点不在一起获取选区中的文本元素
|
217
|
-
let result = vm.dataRangeCaches.flatList.filter(item => {
|
218
|
-
return item.element.isText()
|
219
|
-
})
|
220
|
-
//如果不包含文本元素直接返回false
|
221
|
-
if (result.length == 0) {
|
222
|
-
return false
|
223
|
-
}
|
224
|
-
//判断每个文本元素是否都具有该样式
|
225
|
-
let flag = result.every(item => {
|
226
|
-
//文本元素含有样式进一步判断
|
227
|
-
if (item.element.hasStyles()) {
|
228
|
-
return queryHasValue(item.element.styles, name, value)
|
229
|
-
}
|
230
|
-
//文本元素没有样式直接返回false
|
231
|
-
return false
|
232
|
-
})
|
233
|
-
return flag
|
234
|
-
}
|
235
|
-
|
236
|
-
//查询文本元素是否具有某个标记
|
237
|
-
export const queryTextMark = (vm, name, value) => {
|
238
|
-
//起点和终点在一起
|
239
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
240
|
-
//如果是文本元素并且具有标记
|
241
|
-
if (vm.editor.range.anchor.element.isText() && vm.editor.range.anchor.element.hasMarks()) {
|
242
|
-
return queryHasValue(vm.editor.range.anchor.element.marks, name, value)
|
243
|
-
}
|
244
|
-
//不是文本元素或者没有标记直接返回
|
245
|
-
return false
|
246
|
-
}
|
247
|
-
//起点和终点不在一起获取选区中的文本元素
|
248
|
-
let result = vm.dataRangeCaches.flatList.filter(item => {
|
249
|
-
return item.element.isText()
|
250
|
-
})
|
251
|
-
//如果不包含文本元素直接返回false
|
252
|
-
if (result.length == 0) {
|
253
|
-
return false
|
254
|
-
}
|
255
|
-
//判断每个文本元素是否都具有该标记
|
256
|
-
let flag = result.every(item => {
|
257
|
-
//文本元素含有标记进一步判断
|
258
|
-
if (item.element.hasMarks()) {
|
259
|
-
return queryHasValue(item.element.marks, name, value)
|
260
|
-
}
|
261
|
-
//文本元素没有标记直接返回false
|
262
|
-
return false
|
263
|
-
})
|
264
|
-
return flag
|
265
|
-
}
|
266
|
-
|
267
|
-
//获取链接文字内容,用于预置链接文字
|
268
|
-
export const getLinkText = vm => {
|
269
|
-
//存在选区的情况下预置链接文本值
|
270
|
-
let text = ''
|
271
|
-
vm.dataRangeCaches.flatList.forEach(item => {
|
272
|
-
if (item.element.isText()) {
|
273
|
-
if (item.offset) {
|
274
|
-
text += item.element.textContent.substring(item.offset[0], item.offset[1])
|
275
|
-
} else {
|
276
|
-
text += item.element.textContent || ''
|
277
|
-
}
|
278
|
-
}
|
279
|
-
})
|
280
|
-
return text
|
281
|
-
}
|
282
|
-
|
283
|
-
//获取光标选取内的扁平化元素数组(可能会分割文本元素导致stack变更,同时也会更新选取元素和光标位置)
|
284
|
-
export const getFlatElementsByRange = vm => {
|
285
|
-
//获取选区数据的长度
|
286
|
-
let length = vm.dataRangeCaches.flatList.length
|
287
|
-
//返回的元素数组
|
288
|
-
let elements = []
|
289
|
-
//遍历选区数据
|
290
|
-
for (let i = 0; i < length; i++) {
|
291
|
-
const item = vm.dataRangeCaches.flatList[i]
|
292
|
-
//如果存在offset那么一定是文本元素
|
293
|
-
if (item.offset) {
|
294
|
-
let selectEl = null
|
295
|
-
//文本元素前面一部分在光标范围内
|
296
|
-
if (item.offset[0] == 0 && item.offset[1] < item.element.textContent.length) {
|
297
|
-
const el = item.element.clone()
|
298
|
-
item.element.textContent = item.element.textContent.substring(0, item.offset[1])
|
299
|
-
el.textContent = el.textContent.substring(item.offset[1])
|
300
|
-
vm.editor.addElementAfter(el, item.element)
|
301
|
-
selectEl = item.element
|
302
|
-
}
|
303
|
-
//文本元素后面一部分在光标范围内
|
304
|
-
else if (item.offset[1] == item.element.textContent.length && item.offset[0] > 0) {
|
305
|
-
const el = item.element.clone()
|
306
|
-
item.element.textContent = item.element.textContent.substring(0, item.offset[0])
|
307
|
-
el.textContent = el.textContent.substring(item.offset[0])
|
308
|
-
vm.editor.addElementAfter(el, item.element)
|
309
|
-
selectEl = el
|
310
|
-
}
|
311
|
-
//文本元素的中间一部分在光标范围内
|
312
|
-
else if (item.offset[0] > 0 && item.offset[1] < item.element.textContent.length) {
|
313
|
-
const el = item.element.clone()
|
314
|
-
const el2 = item.element.clone()
|
315
|
-
item.element.textContent = item.element.textContent.substring(0, item.offset[0])
|
316
|
-
el.textContent = el.textContent.substring(item.offset[0], item.offset[1])
|
317
|
-
el2.textContent = el2.textContent.substring(item.offset[1])
|
318
|
-
vm.editor.addElementAfter(el, item.element)
|
319
|
-
vm.editor.addElementAfter(el2, el)
|
320
|
-
selectEl = el
|
321
|
-
}
|
322
|
-
//如果selectEl存在证明文本元素被分割了
|
323
|
-
if (selectEl) {
|
324
|
-
//如果i为0的话肯定是起点
|
325
|
-
if (i == 0) {
|
326
|
-
vm.editor.range.anchor.moveToStart(selectEl)
|
327
|
-
}
|
328
|
-
//如果i是最后一个序列的话肯定是终点
|
329
|
-
if (i == length - 1) {
|
330
|
-
vm.editor.range.focus.moveToEnd(selectEl)
|
331
|
-
}
|
332
|
-
elements.push(selectEl)
|
333
|
-
}
|
334
|
-
} else {
|
335
|
-
elements.push(item.element)
|
336
|
-
}
|
337
|
-
}
|
338
|
-
return elements
|
339
|
-
}
|
340
|
-
|
341
|
-
//将某个元素转为段落标签
|
342
|
-
export const elementToParagraph = function (element) {
|
343
|
-
element.marks = null
|
344
|
-
element.styles = null
|
345
|
-
element.parsedom = AlexElement.BLOCK_NODE
|
346
|
-
}
|
347
|
-
|
348
|
-
//其他元素转为有序或者无序列表
|
349
|
-
export const elementToList = function (element, ordered = false) {
|
350
|
-
//如果是列表则返回
|
351
|
-
if (isList(element, ordered)) {
|
352
|
-
return
|
353
|
-
}
|
354
|
-
//先转为段落
|
355
|
-
elementToParagraph(element)
|
356
|
-
//然后转为列表
|
357
|
-
element.parsedom = 'div'
|
358
|
-
if (!element.hasMarks()) {
|
359
|
-
element.marks = {}
|
360
|
-
}
|
361
|
-
element.marks['data-editify-list'] = ordered ? 'ol' : 'ul'
|
362
|
-
}
|
363
|
-
|
364
|
-
//其他元素转为任务列表
|
365
|
-
export const elementToTask = function (element) {
|
366
|
-
//如果是任务列表则返回
|
367
|
-
if (isTask(element)) {
|
368
|
-
return
|
369
|
-
}
|
370
|
-
//先转为段落
|
371
|
-
elementToParagraph(element)
|
372
|
-
//然后转为任务列表
|
373
|
-
element.parsedom = 'div'
|
374
|
-
if (!element.hasMarks()) {
|
375
|
-
element.marks = {}
|
376
|
-
}
|
377
|
-
element.marks['data-editify-task'] = 'uncheck'
|
378
|
-
}
|
379
|
-
|
380
|
-
//设置标题
|
381
|
-
export const setHeading = (vm, parsedom) => {
|
382
|
-
const values = getButtonOptionsConfig(vm.$editTrans, vm.$editLocale).heading.map(item => {
|
383
|
-
return item.value
|
384
|
-
})
|
385
|
-
if (!values.includes(parsedom)) {
|
386
|
-
throw new Error('The parameter supports only h1-h6 and p')
|
387
|
-
}
|
388
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
389
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
390
|
-
//先转为段落
|
391
|
-
elementToParagraph(block)
|
392
|
-
//设置标题
|
393
|
-
block.parsedom = parsedom
|
394
|
-
} else {
|
395
|
-
vm.dataRangeCaches.list.forEach(el => {
|
396
|
-
if (el.element.isBlock()) {
|
397
|
-
elementToParagraph(el.element)
|
398
|
-
el.element.parsedom = parsedom
|
399
|
-
} else {
|
400
|
-
const block = el.element.getBlock()
|
401
|
-
elementToParagraph(block)
|
402
|
-
block.parsedom = parsedom
|
403
|
-
}
|
404
|
-
})
|
405
|
-
}
|
406
|
-
}
|
407
|
-
|
408
|
-
//根级块元素或者内部块元素增加缩进
|
409
|
-
export const setIndentIncrease = vm => {
|
410
|
-
const fn = element => {
|
411
|
-
if (element.hasStyles()) {
|
412
|
-
if (element.styles.hasOwnProperty('text-indent')) {
|
413
|
-
let val = element.styles['text-indent']
|
414
|
-
if (val.endsWith('em')) {
|
415
|
-
val = parseFloat(val)
|
416
|
-
} else {
|
417
|
-
val = 0
|
418
|
-
}
|
419
|
-
element.styles['text-indent'] = `${val + 2}em`
|
420
|
-
} else {
|
421
|
-
element.styles['text-indent'] = '2em'
|
422
|
-
}
|
423
|
-
} else {
|
424
|
-
element.styles = {
|
425
|
-
'text-indent': '2em'
|
426
|
-
}
|
427
|
-
}
|
428
|
-
}
|
429
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
430
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
431
|
-
const inblock = vm.editor.range.anchor.element.getInblock()
|
432
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
433
|
-
fn(inblock)
|
434
|
-
} else if (!block.isPreStyle()) {
|
435
|
-
fn(block)
|
436
|
-
}
|
437
|
-
} else {
|
438
|
-
vm.dataRangeCaches.list.forEach(item => {
|
439
|
-
const block = item.element.getBlock()
|
440
|
-
const inblock = item.element.getInblock()
|
441
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
442
|
-
fn(inblock)
|
443
|
-
} else if (!block.isPreStyle()) {
|
444
|
-
fn(block)
|
445
|
-
}
|
446
|
-
})
|
447
|
-
}
|
448
|
-
}
|
449
|
-
|
450
|
-
//根级块元素或者内部块元素减少缩进
|
451
|
-
export const setIndentDecrease = vm => {
|
452
|
-
const fn = element => {
|
453
|
-
if (element.hasStyles() && element.styles.hasOwnProperty('text-indent')) {
|
454
|
-
let val = element.styles['text-indent']
|
455
|
-
if (val.endsWith('em')) {
|
456
|
-
val = parseFloat(val)
|
457
|
-
} else {
|
458
|
-
val = 0
|
459
|
-
}
|
460
|
-
element.styles['text-indent'] = `${val - 2 >= 0 ? val - 2 : 0}em`
|
461
|
-
}
|
462
|
-
}
|
463
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
464
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
465
|
-
const inblock = vm.editor.range.anchor.element.getInblock()
|
466
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
467
|
-
fn(inblock)
|
468
|
-
} else if (!block.isPreStyle()) {
|
469
|
-
fn(block)
|
470
|
-
}
|
471
|
-
} else {
|
472
|
-
vm.dataRangeCaches.list.forEach(item => {
|
473
|
-
const block = item.element.getBlock()
|
474
|
-
const inblock = item.element.getInblock()
|
475
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
476
|
-
fn(inblock)
|
477
|
-
} else if (!block.isPreStyle()) {
|
478
|
-
fn(block)
|
479
|
-
}
|
480
|
-
})
|
481
|
-
}
|
482
|
-
}
|
483
|
-
|
484
|
-
//插入或者取消引用
|
485
|
-
export const setQuote = vm => {
|
486
|
-
//是否都在引用里
|
487
|
-
const flag = isRangeInQuote(vm)
|
488
|
-
//起点和终点在一起
|
489
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
490
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
491
|
-
elementToParagraph(block)
|
492
|
-
if (!flag) {
|
493
|
-
block.parsedom = 'blockquote'
|
494
|
-
}
|
495
|
-
}
|
496
|
-
//起点和终点不在一起
|
497
|
-
else {
|
498
|
-
let blocks = []
|
499
|
-
vm.dataRangeCaches.list.forEach(item => {
|
500
|
-
const block = item.element.getBlock()
|
501
|
-
const exist = blocks.some(el => block.isEqual(el))
|
502
|
-
if (!exist) {
|
503
|
-
blocks.push(block)
|
504
|
-
}
|
505
|
-
})
|
506
|
-
blocks.forEach(block => {
|
507
|
-
elementToParagraph(block)
|
508
|
-
if (!flag) {
|
509
|
-
block.parsedom = 'blockquote'
|
510
|
-
}
|
511
|
-
})
|
512
|
-
}
|
513
|
-
}
|
514
|
-
|
515
|
-
//设置对齐方式,参数取值justify/left/right/center
|
516
|
-
export const setAlign = (vm, value) => {
|
517
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
518
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
519
|
-
const inblock = vm.editor.range.anchor.element.getInblock()
|
520
|
-
if (inblock) {
|
521
|
-
if (inblock.hasStyles()) {
|
522
|
-
inblock.styles['text-align'] = value
|
523
|
-
} else {
|
524
|
-
inblock.styles = {
|
525
|
-
'text-align': value
|
526
|
-
}
|
527
|
-
}
|
528
|
-
} else {
|
529
|
-
if (block.hasStyles()) {
|
530
|
-
block.styles['text-align'] = value
|
531
|
-
} else {
|
532
|
-
block.styles = {
|
533
|
-
'text-align': value
|
534
|
-
}
|
535
|
-
}
|
536
|
-
}
|
537
|
-
} else {
|
538
|
-
vm.dataRangeCaches.list.forEach(el => {
|
539
|
-
if (el.element.isBlock() || el.element.isInblock()) {
|
540
|
-
if (el.element.hasStyles()) {
|
541
|
-
el.element.styles['text-align'] = value
|
542
|
-
} else {
|
543
|
-
el.element.styles = {
|
544
|
-
'text-align': value
|
545
|
-
}
|
546
|
-
}
|
547
|
-
} else {
|
548
|
-
const block = el.element.getBlock()
|
549
|
-
const inblock = el.element.getInblock()
|
550
|
-
if (inblock) {
|
551
|
-
if (inblock.hasStyles()) {
|
552
|
-
inblock.styles['text-align'] = value
|
553
|
-
} else {
|
554
|
-
inblock.styles = {
|
555
|
-
'text-align': value
|
556
|
-
}
|
557
|
-
}
|
558
|
-
} else {
|
559
|
-
if (block.hasStyles()) {
|
560
|
-
block.styles['text-align'] = value
|
561
|
-
} else {
|
562
|
-
block.styles = {
|
563
|
-
'text-align': value
|
564
|
-
}
|
565
|
-
}
|
566
|
-
}
|
567
|
-
}
|
568
|
-
})
|
569
|
-
}
|
570
|
-
}
|
571
|
-
|
572
|
-
//插入或者取消 有序或者无序列表 ordered为true表示有序列表
|
573
|
-
export const setList = (vm, ordered) => {
|
574
|
-
//是否都在列表内
|
575
|
-
const flag = isRangeInList(vm, ordered)
|
576
|
-
//起点和终点在一起
|
577
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
578
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
579
|
-
if (flag) {
|
580
|
-
elementToParagraph(block)
|
581
|
-
} else {
|
582
|
-
elementToList(block, ordered)
|
583
|
-
}
|
584
|
-
}
|
585
|
-
//起点和终点不在一起
|
586
|
-
else {
|
587
|
-
let blocks = []
|
588
|
-
vm.dataRangeCaches.list.forEach(item => {
|
589
|
-
const block = item.element.getBlock()
|
590
|
-
const exist = blocks.some(el => block.isEqual(el))
|
591
|
-
if (!exist) {
|
592
|
-
blocks.push(block)
|
593
|
-
}
|
594
|
-
})
|
595
|
-
blocks.forEach(block => {
|
596
|
-
if (flag) {
|
597
|
-
elementToParagraph(block)
|
598
|
-
} else {
|
599
|
-
elementToList(block, ordered)
|
600
|
-
}
|
601
|
-
})
|
602
|
-
}
|
603
|
-
}
|
604
|
-
|
605
|
-
//插入或者取消任务列表
|
606
|
-
export const setTask = vm => {
|
607
|
-
//是否都在任务列表那
|
608
|
-
const flag = isRangeInTask(vm)
|
609
|
-
//起点和终点在一起
|
610
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
611
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
612
|
-
if (flag) {
|
613
|
-
elementToParagraph(block)
|
614
|
-
} else {
|
615
|
-
elementToTask(block)
|
616
|
-
}
|
617
|
-
}
|
618
|
-
//起点和终点不在一起
|
619
|
-
else {
|
620
|
-
let blocks = []
|
621
|
-
vm.dataRangeCaches.list.forEach(item => {
|
622
|
-
const block = item.element.getBlock()
|
623
|
-
const exist = blocks.some(el => block.isEqual(el))
|
624
|
-
if (!exist) {
|
625
|
-
blocks.push(block)
|
626
|
-
}
|
627
|
-
})
|
628
|
-
blocks.forEach(block => {
|
629
|
-
if (flag) {
|
630
|
-
elementToParagraph(block)
|
631
|
-
} else {
|
632
|
-
elementToTask(block)
|
633
|
-
}
|
634
|
-
})
|
635
|
-
}
|
636
|
-
}
|
637
|
-
|
638
|
-
//设置文本元素的样式,styles为{ 'font-weight':'bold' }这类格式
|
639
|
-
export const setTextStyle = (vm, styles) => {
|
640
|
-
//起点和终点在一起
|
641
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
642
|
-
//如果是空白文本元素直接设置样式
|
643
|
-
if (vm.editor.range.anchor.element.isSpaceText()) {
|
644
|
-
if (vm.editor.range.anchor.element.hasStyles()) {
|
645
|
-
Object.assign(vm.editor.range.anchor.element.styles, cloneData(styles))
|
646
|
-
} else {
|
647
|
-
vm.editor.range.anchor.element.styles = cloneData(styles)
|
648
|
-
}
|
649
|
-
}
|
650
|
-
//如果是文本元素
|
651
|
-
else if (vm.editor.range.anchor.element.isText()) {
|
652
|
-
//新建一个空白文本元素
|
653
|
-
const el = AlexElement.getSpaceElement()
|
654
|
-
//继承文本元素的样式和标记
|
655
|
-
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
656
|
-
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
657
|
-
//设置样式
|
658
|
-
if (el.hasStyles()) {
|
659
|
-
Object.assign(el.styles, cloneData(styles))
|
660
|
-
} else {
|
661
|
-
el.styles = cloneData(styles)
|
662
|
-
}
|
663
|
-
//插入空白文本元素
|
664
|
-
vm.editor.insertElement(el)
|
665
|
-
}
|
666
|
-
//如果是自闭合元素
|
667
|
-
else {
|
668
|
-
const el = AlexElement.getSpaceElement()
|
669
|
-
el.styles = cloneData(styles)
|
670
|
-
vm.editor.insertElement(el)
|
671
|
-
}
|
672
|
-
}
|
673
|
-
//不在同一个点
|
674
|
-
else {
|
675
|
-
const elements = getFlatElementsByRange(vm)
|
676
|
-
elements.forEach(ele => {
|
677
|
-
if (ele.isText()) {
|
678
|
-
if (ele.hasStyles()) {
|
679
|
-
Object.assign(ele.styles, cloneData(styles))
|
680
|
-
} else {
|
681
|
-
ele.styles = cloneData(styles)
|
682
|
-
}
|
683
|
-
}
|
684
|
-
})
|
685
|
-
}
|
686
|
-
}
|
687
|
-
|
688
|
-
//设置文本元素的标记,marks为{ 'class':'a' }这类格式
|
689
|
-
export const setTextMark = (vm, marks) => {
|
690
|
-
if (!DapCommon.isObject(marks)) {
|
691
|
-
throw new Error('The argument must be an object')
|
692
|
-
}
|
693
|
-
//起点和终点在一起
|
694
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
695
|
-
//如果是空白文本元素直接设置标记
|
696
|
-
if (vm.editor.range.anchor.element.isSpaceText()) {
|
697
|
-
if (vm.editor.range.anchor.element.hasMarks()) {
|
698
|
-
Object.assign(vm.editor.range.anchor.element.marks, cloneData(marks))
|
699
|
-
} else {
|
700
|
-
vm.editor.range.anchor.element.marks = cloneData(marks)
|
701
|
-
}
|
702
|
-
}
|
703
|
-
//如果是文本元素
|
704
|
-
else if (vm.editor.range.anchor.element.isText()) {
|
705
|
-
//新建一个空白文本元素
|
706
|
-
const el = AlexElement.getSpaceElement()
|
707
|
-
//继承文本元素的样式和标记
|
708
|
-
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
709
|
-
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
710
|
-
//设置标记
|
711
|
-
if (el.hasMarks()) {
|
712
|
-
Object.assign(el.marks, cloneData(marks))
|
713
|
-
} else {
|
714
|
-
el.marks = cloneData(marks)
|
715
|
-
}
|
716
|
-
//插入空白文本元素
|
717
|
-
vm.editor.insertElement(el)
|
718
|
-
}
|
719
|
-
//如果是自闭合元素
|
720
|
-
else {
|
721
|
-
const el = AlexElement.getSpaceElement()
|
722
|
-
el.marks = cloneData(marks)
|
723
|
-
vm.editor.insertElement(el)
|
724
|
-
}
|
725
|
-
}
|
726
|
-
//不在同一个点
|
727
|
-
else {
|
728
|
-
const elements = getFlatElementsByRange(vm)
|
729
|
-
elements.forEach(ele => {
|
730
|
-
if (ele.isText()) {
|
731
|
-
if (ele.hasMarks()) {
|
732
|
-
Object.assign(ele.marks, cloneData(marks))
|
733
|
-
} else {
|
734
|
-
ele.marks = cloneData(marks)
|
735
|
-
}
|
736
|
-
}
|
737
|
-
})
|
738
|
-
}
|
739
|
-
}
|
740
|
-
|
741
|
-
//移除文本元素的样式,styleNames是样式名称数组,如果不存在则移除全部样式
|
742
|
-
export const removeTextStyle = (vm, styleNames) => {
|
743
|
-
//移除样式的方法
|
744
|
-
const removeFn = el => {
|
745
|
-
//如果参数是数组,表示删除指定的样式
|
746
|
-
if (Array.isArray(styleNames)) {
|
747
|
-
if (el.hasStyles()) {
|
748
|
-
let styles = {}
|
749
|
-
Object.keys(el.styles).forEach(key => {
|
750
|
-
if (!styleNames.includes(key)) {
|
751
|
-
styles[key] = el.styles[key]
|
752
|
-
}
|
753
|
-
})
|
754
|
-
el.styles = styles
|
755
|
-
}
|
756
|
-
}
|
757
|
-
//如果没有参数,则表示删除所有的样式
|
758
|
-
else {
|
759
|
-
el.styles = null
|
760
|
-
}
|
761
|
-
}
|
762
|
-
//如果起点和终点在一起
|
763
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
764
|
-
//如果是空白文本元素直接移除样式
|
765
|
-
if (vm.editor.range.anchor.element.isSpaceText()) {
|
766
|
-
removeFn(vm.editor.range.anchor.element)
|
767
|
-
}
|
768
|
-
//如果是文本元素则新建一个空白文本元素
|
769
|
-
else if (vm.editor.range.anchor.element.isText()) {
|
770
|
-
const el = AlexElement.getSpaceElement()
|
771
|
-
//继承文本元素的样式和标记
|
772
|
-
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
773
|
-
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
774
|
-
//移除样式
|
775
|
-
removeFn(el)
|
776
|
-
//插入
|
777
|
-
vm.editor.insertElement(el)
|
778
|
-
}
|
779
|
-
}
|
780
|
-
//起点和终点不在一起
|
781
|
-
else {
|
782
|
-
const elements = getFlatElementsByRange(vm)
|
783
|
-
elements.forEach(ele => {
|
784
|
-
if (ele.isText()) {
|
785
|
-
removeFn(ele)
|
786
|
-
}
|
787
|
-
})
|
788
|
-
}
|
789
|
-
}
|
790
|
-
|
791
|
-
//移除文本元素的标记,markNames是标记名称数组,如果不存在则移除全部标记
|
792
|
-
export const removeTextMark = (vm, markNames) => {
|
793
|
-
//移除样式的方法
|
794
|
-
const removeFn = el => {
|
795
|
-
//如果参数是数组,表示删除指定的样式
|
796
|
-
if (Array.isArray(markNames)) {
|
797
|
-
if (el.hasMarks()) {
|
798
|
-
let marks = {}
|
799
|
-
Object.keys(el.marks).forEach(key => {
|
800
|
-
if (!markNames.includes(key)) {
|
801
|
-
marks[key] = el.marks[key]
|
802
|
-
}
|
803
|
-
})
|
804
|
-
el.marks = marks
|
805
|
-
}
|
806
|
-
}
|
807
|
-
//如果没有参数,则表示删除所有的样式
|
808
|
-
else {
|
809
|
-
el.marks = null
|
810
|
-
}
|
811
|
-
}
|
812
|
-
//如果起点和终点在一起
|
813
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
814
|
-
//如果是空白文本元素直接移除标记
|
815
|
-
if (vm.editor.range.anchor.element.isSpaceText()) {
|
816
|
-
removeFn(vm.editor.range.anchor.element)
|
817
|
-
}
|
818
|
-
//如果是文本元素则新建一个空白文本元素
|
819
|
-
else if (vm.editor.range.anchor.element.isText()) {
|
820
|
-
const el = AlexElement.getSpaceElement()
|
821
|
-
//继承文本元素的样式和标记
|
822
|
-
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
823
|
-
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
824
|
-
//移除标记
|
825
|
-
removeFn(el)
|
826
|
-
//插入
|
827
|
-
vm.editor.insertElement(el)
|
828
|
-
}
|
829
|
-
}
|
830
|
-
//起点和终点不在一起
|
831
|
-
else {
|
832
|
-
const elements = getFlatElementsByRange(vm)
|
833
|
-
elements.forEach(ele => {
|
834
|
-
if (ele.isText()) {
|
835
|
-
removeFn(ele)
|
836
|
-
}
|
837
|
-
})
|
838
|
-
}
|
839
|
-
}
|
840
|
-
|
841
|
-
//设置块元素或者根级块元素的行高
|
842
|
-
export const setLineHeight = (vm, value) => {
|
843
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
844
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
845
|
-
const inblock = vm.editor.range.anchor.element.getInblock()
|
846
|
-
if (inblock) {
|
847
|
-
if (inblock.hasStyles()) {
|
848
|
-
inblock.styles['line-height'] = value
|
849
|
-
} else {
|
850
|
-
inblock.styles = {
|
851
|
-
'line-height': value
|
852
|
-
}
|
853
|
-
}
|
854
|
-
} else {
|
855
|
-
if (block.hasStyles()) {
|
856
|
-
block.styles['line-height'] = value
|
857
|
-
} else {
|
858
|
-
block.styles = {
|
859
|
-
'line-height': value
|
860
|
-
}
|
861
|
-
}
|
862
|
-
}
|
863
|
-
} else {
|
864
|
-
vm.dataRangeCaches.list.forEach(el => {
|
865
|
-
if (el.element.isBlock() || el.element.isInblock()) {
|
866
|
-
if (el.element.hasStyles()) {
|
867
|
-
el.element.styles['line-height'] = value
|
868
|
-
} else {
|
869
|
-
el.element.styles = {
|
870
|
-
'line-height': value
|
871
|
-
}
|
872
|
-
}
|
873
|
-
} else {
|
874
|
-
const block = el.element.getBlock()
|
875
|
-
const inblock = el.element.getInblock()
|
876
|
-
if (inblock) {
|
877
|
-
if (inblock.hasStyles()) {
|
878
|
-
inblock.styles['line-height'] = value
|
879
|
-
} else {
|
880
|
-
inblock.styles = {
|
881
|
-
'line-height': value
|
882
|
-
}
|
883
|
-
}
|
884
|
-
} else {
|
885
|
-
if (block.hasStyles()) {
|
886
|
-
block.styles['line-height'] = value
|
887
|
-
} else {
|
888
|
-
block.styles = {
|
889
|
-
'line-height': value
|
890
|
-
}
|
891
|
-
}
|
892
|
-
}
|
893
|
-
}
|
894
|
-
})
|
895
|
-
}
|
896
|
-
}
|
897
|
-
|
898
|
-
//插入链接
|
899
|
-
export const insertLink = (vm, text, url, newOpen) => {
|
900
|
-
if (!text) {
|
901
|
-
text = url
|
902
|
-
}
|
903
|
-
const marks = {
|
904
|
-
href: url
|
905
|
-
}
|
906
|
-
if (newOpen) {
|
907
|
-
marks.target = '_blank'
|
908
|
-
}
|
909
|
-
const linkEle = new AlexElement('inline', 'a', marks, null, null)
|
910
|
-
const textEle = new AlexElement('text', null, null, null, text)
|
911
|
-
vm.editor.addElementTo(textEle, linkEle)
|
912
|
-
vm.editor.insertElement(linkEle)
|
913
|
-
}
|
914
|
-
|
915
|
-
//插入图片
|
916
|
-
export const insertImage = (vm, value) => {
|
917
|
-
const image = new AlexElement(
|
918
|
-
'closed',
|
919
|
-
'img',
|
920
|
-
{
|
921
|
-
src: value
|
922
|
-
},
|
923
|
-
null,
|
924
|
-
null
|
925
|
-
)
|
926
|
-
vm.editor.insertElement(image)
|
927
|
-
}
|
928
|
-
|
929
|
-
//插入视频
|
930
|
-
export const insertVideo = (vm, value) => {
|
931
|
-
const video = new AlexElement(
|
932
|
-
'closed',
|
933
|
-
'video',
|
934
|
-
{
|
935
|
-
src: value
|
936
|
-
},
|
937
|
-
null,
|
938
|
-
null
|
939
|
-
)
|
940
|
-
vm.editor.insertElement(video)
|
941
|
-
const leftSpace = AlexElement.getSpaceElement()
|
942
|
-
const rightSpace = AlexElement.getSpaceElement()
|
943
|
-
vm.editor.addElementAfter(rightSpace, video)
|
944
|
-
vm.editor.addElementBefore(leftSpace, video)
|
945
|
-
vm.editor.range.anchor.moveToEnd(rightSpace)
|
946
|
-
vm.editor.range.focus.moveToEnd(rightSpace)
|
947
|
-
}
|
948
|
-
|
949
|
-
//插入表格
|
950
|
-
export const insertTable = (vm, rowLength, colLength) => {
|
951
|
-
const table = new AlexElement('block', 'table', null, null, null)
|
952
|
-
const tbody = new AlexElement('inblock', 'tbody', null, null, null)
|
953
|
-
vm.editor.addElementTo(tbody, table)
|
954
|
-
for (let i = 0; i < rowLength; i++) {
|
955
|
-
const row = new AlexElement('inblock', 'tr', null, null, null)
|
956
|
-
for (let j = 0; j < colLength; j++) {
|
957
|
-
const column = new AlexElement('inblock', 'td', null, null, null)
|
958
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
959
|
-
vm.editor.addElementTo(breakEl, column)
|
960
|
-
vm.editor.addElementTo(column, row)
|
961
|
-
}
|
962
|
-
vm.editor.addElementTo(row, tbody)
|
963
|
-
}
|
964
|
-
vm.editor.insertElement(table)
|
965
|
-
//在表格后创建一个段落
|
966
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
967
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
968
|
-
vm.editor.addElementTo(breakEl, paragraph)
|
969
|
-
vm.editor.addElementAfter(paragraph, table)
|
970
|
-
vm.editor.range.anchor.moveToStart(tbody)
|
971
|
-
vm.editor.range.focus.moveToStart(tbody)
|
972
|
-
}
|
973
|
-
|
974
|
-
//插入或者取消代码块
|
975
|
-
export const insertCodeBlock = vm => {
|
976
|
-
const pre = getCurrentParsedomElement(vm, 'pre')
|
977
|
-
if (pre) {
|
978
|
-
let content = ''
|
979
|
-
AlexElement.flatElements(pre.children)
|
980
|
-
.filter(item => {
|
981
|
-
return item.isText()
|
982
|
-
})
|
983
|
-
.forEach(item => {
|
984
|
-
content += item.textContent
|
985
|
-
})
|
986
|
-
const splits = content.split('\n')
|
987
|
-
splits.forEach(item => {
|
988
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
989
|
-
const text = new AlexElement('text', null, null, null, item)
|
990
|
-
vm.editor.addElementTo(text, paragraph)
|
991
|
-
vm.editor.addElementBefore(paragraph, pre)
|
992
|
-
})
|
993
|
-
pre.toEmpty()
|
994
|
-
} else {
|
995
|
-
//起点和终点在一起
|
996
|
-
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
997
|
-
const block = vm.editor.range.anchor.element.getBlock()
|
998
|
-
elementToParagraph(block)
|
999
|
-
block.parsedom = 'pre'
|
1000
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1001
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1002
|
-
vm.editor.addElementTo(breakEl, paragraph)
|
1003
|
-
vm.editor.addElementAfter(paragraph, block)
|
1004
|
-
}
|
1005
|
-
//起点和终点不在一起
|
1006
|
-
else {
|
1007
|
-
vm.editor.range.anchor.moveToStart(vm.dataRangeCaches.list[0].element.getBlock())
|
1008
|
-
vm.editor.range.focus.moveToEnd(vm.dataRangeCaches.list[vm.dataRangeCaches.list.length - 1].element.getBlock())
|
1009
|
-
const res = vm.dataRangeCaches.flatList.filter(el => el.element.isText())
|
1010
|
-
const obj = {}
|
1011
|
-
res.forEach(el => {
|
1012
|
-
if (obj[el.element.getBlock().key]) {
|
1013
|
-
obj[el.element.getBlock().key].push(el.element.clone())
|
1014
|
-
} else {
|
1015
|
-
obj[el.element.getBlock().key] = [el.element.clone()]
|
1016
|
-
}
|
1017
|
-
})
|
1018
|
-
const pre = new AlexElement('block', 'pre', null, null, null)
|
1019
|
-
Object.keys(obj).forEach((key, index) => {
|
1020
|
-
if (index > 0) {
|
1021
|
-
const text = new AlexElement('text', null, null, null, '\n')
|
1022
|
-
if (pre.hasChildren()) {
|
1023
|
-
vm.editor.addElementTo(text, pre, pre.children.length)
|
1024
|
-
} else {
|
1025
|
-
vm.editor.addElementTo(text, pre)
|
1026
|
-
}
|
1027
|
-
}
|
1028
|
-
obj[key].forEach(el => {
|
1029
|
-
if (pre.hasChildren()) {
|
1030
|
-
vm.editor.addElementTo(el, pre, pre.children.length)
|
1031
|
-
} else {
|
1032
|
-
vm.editor.addElementTo(el, pre)
|
1033
|
-
}
|
1034
|
-
})
|
1035
|
-
})
|
1036
|
-
vm.editor.delete()
|
1037
|
-
vm.editor.insertElement(pre)
|
1038
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1039
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1040
|
-
vm.editor.addElementTo(breakEl, paragraph)
|
1041
|
-
vm.editor.addElementAfter(paragraph, pre)
|
1042
|
-
}
|
1043
|
-
}
|
1044
|
-
}
|
1
|
+
/**
|
2
|
+
* 这里的方法都是对编辑器内容元素进行判断或者操作的方法,不涉及到格式化、dom渲染和光标渲染
|
3
|
+
*/
|
4
|
+
import { AlexElement } from 'alex-editor'
|
5
|
+
import { common as DapCommon } from 'dap-util'
|
6
|
+
import { cloneData, queryHasValue, getButtonOptionsConfig } from './tool'
|
7
|
+
|
8
|
+
//判断元素是否在某个标签下,如果是返回该标签对应的元素,否则返回null
|
9
|
+
export const getParsedomElementByElement = (element, parsedom) => {
|
10
|
+
if (element.isBlock()) {
|
11
|
+
return element.parsedom == parsedom ? element : null
|
12
|
+
}
|
13
|
+
if (!element.isText() && element.parsedom == parsedom) {
|
14
|
+
return element
|
15
|
+
}
|
16
|
+
return getParsedomElementByElement(element.parent, parsedom)
|
17
|
+
}
|
18
|
+
|
19
|
+
//获取光标是否在指定标签下,如果是返回该标签对应的元素,否则返回null
|
20
|
+
export const getCurrentParsedomElement = (vm, parsedom) => {
|
21
|
+
if (vm.editor.range.anchor.element.isEqual(vm.editor.range.focus.element)) {
|
22
|
+
return getParsedomElementByElement(vm.editor.range.anchor.element, parsedom)
|
23
|
+
}
|
24
|
+
const arr = vm.dataRangeCaches.list.map(item => {
|
25
|
+
return getParsedomElementByElement(item.element, parsedom)
|
26
|
+
})
|
27
|
+
let hasNull = arr.some(el => {
|
28
|
+
return el == null
|
29
|
+
})
|
30
|
+
//如果存在null,则表示有的选区元素不在指定标签下,返回null
|
31
|
+
if (hasNull) {
|
32
|
+
return null
|
33
|
+
}
|
34
|
+
//如果只有一个元素,则返回该元素
|
35
|
+
if (arr.length == 1) {
|
36
|
+
return arr[0]
|
37
|
+
}
|
38
|
+
//默认数组中的元素都相等
|
39
|
+
let flag = true
|
40
|
+
for (let i = 1; i < arr.length; i++) {
|
41
|
+
if (!arr[i].isEqual(arr[0])) {
|
42
|
+
flag = false
|
43
|
+
break
|
44
|
+
}
|
45
|
+
}
|
46
|
+
//如果相等,则返回该元素
|
47
|
+
if (flag) {
|
48
|
+
return arr[0]
|
49
|
+
}
|
50
|
+
return null
|
51
|
+
}
|
52
|
+
|
53
|
+
//判断元素是否在有序列表或者无序列表下
|
54
|
+
export const elementIsInList = (element, ordered) => {
|
55
|
+
if (isList(element, ordered)) {
|
56
|
+
return true
|
57
|
+
}
|
58
|
+
if (element.parent) {
|
59
|
+
return elementIsInList(element.parent, ordered)
|
60
|
+
}
|
61
|
+
return false
|
62
|
+
}
|
63
|
+
|
64
|
+
//判断元素是否在任务列表下
|
65
|
+
export const elementIsInTask = element => {
|
66
|
+
if (isTask(element)) {
|
67
|
+
return true
|
68
|
+
}
|
69
|
+
if (element.parent) {
|
70
|
+
return elementIsInTask(element.parent)
|
71
|
+
}
|
72
|
+
return false
|
73
|
+
}
|
74
|
+
|
75
|
+
//判断元素是否有序或者无序列表
|
76
|
+
export const isList = function (element, ordered = false) {
|
77
|
+
return element.parsedom == 'div' && element.hasMarks() && element.marks['data-editify-list'] == (ordered ? 'ol' : 'ul')
|
78
|
+
}
|
79
|
+
|
80
|
+
//判断元素是否任务列表
|
81
|
+
export const isTask = function (element) {
|
82
|
+
return element.parsedom == 'div' && element.hasMarks() && element.marks.hasOwnProperty('data-editify-task')
|
83
|
+
}
|
84
|
+
|
85
|
+
//选区是否含有代码块
|
86
|
+
export const hasPreInRange = vm => {
|
87
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
88
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'pre')
|
89
|
+
}
|
90
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
91
|
+
return !!getParsedomElementByElement(item.element, 'pre')
|
92
|
+
})
|
93
|
+
}
|
94
|
+
|
95
|
+
//选区是否全部在代码块内
|
96
|
+
export const isRangeInPre = vm => {
|
97
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
98
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'pre')
|
99
|
+
}
|
100
|
+
return vm.dataRangeCaches.list.every(item => {
|
101
|
+
return !!getParsedomElementByElement(item.element, 'pre')
|
102
|
+
})
|
103
|
+
}
|
104
|
+
|
105
|
+
//选区是否含有引用
|
106
|
+
export const hasQuoteInRange = vm => {
|
107
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
108
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'blockquote')
|
109
|
+
}
|
110
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
111
|
+
return !!getParsedomElementByElement(item.element, 'blockquote')
|
112
|
+
})
|
113
|
+
}
|
114
|
+
|
115
|
+
//选区是否全部在引用内
|
116
|
+
export const isRangeInQuote = vm => {
|
117
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
118
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'blockquote')
|
119
|
+
}
|
120
|
+
return vm.dataRangeCaches.list.every(item => {
|
121
|
+
return !!getParsedomElementByElement(item.element, 'blockquote')
|
122
|
+
})
|
123
|
+
}
|
124
|
+
|
125
|
+
//选区是否含有有序列表或者无序列表
|
126
|
+
export const hasListInRange = (vm, ordered = false) => {
|
127
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
128
|
+
return elementIsInList(vm.editor.range.anchor.element, ordered)
|
129
|
+
}
|
130
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
131
|
+
return elementIsInList(item.element, ordered)
|
132
|
+
})
|
133
|
+
}
|
134
|
+
|
135
|
+
//选区是否全部在有序列表或者无序列表内
|
136
|
+
export const isRangeInList = (vm, ordered = false) => {
|
137
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
138
|
+
return elementIsInList(vm.editor.range.anchor.element, ordered)
|
139
|
+
}
|
140
|
+
return vm.dataRangeCaches.list.every(item => {
|
141
|
+
return elementIsInList(item.element, ordered)
|
142
|
+
})
|
143
|
+
}
|
144
|
+
|
145
|
+
//选区是否含有任务列表
|
146
|
+
export const hasTaskInRange = vm => {
|
147
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
148
|
+
return elementIsInTask(vm.editor.range.anchor.element)
|
149
|
+
}
|
150
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
151
|
+
return elementIsInTask(item.element)
|
152
|
+
})
|
153
|
+
}
|
154
|
+
|
155
|
+
//选区是否全部在任务列表里
|
156
|
+
export const isRangeInTask = vm => {
|
157
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
158
|
+
return elementIsInTask(vm.editor.range.anchor.element)
|
159
|
+
}
|
160
|
+
return vm.dataRangeCaches.list.every(item => {
|
161
|
+
return elementIsInTask(item.element)
|
162
|
+
})
|
163
|
+
}
|
164
|
+
|
165
|
+
//选区是否含有链接
|
166
|
+
export const hasLinkInRange = vm => {
|
167
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
168
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'a')
|
169
|
+
}
|
170
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
171
|
+
return !!getParsedomElementByElement(item.element, 'a')
|
172
|
+
})
|
173
|
+
}
|
174
|
+
|
175
|
+
//选区是否含有表格
|
176
|
+
export const hasTableInRange = vm => {
|
177
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
178
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'table')
|
179
|
+
}
|
180
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
181
|
+
return !!getParsedomElementByElement(item.element, 'table')
|
182
|
+
})
|
183
|
+
}
|
184
|
+
|
185
|
+
//选区是否含有图片
|
186
|
+
export const hasImageInRange = vm => {
|
187
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
188
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'img')
|
189
|
+
}
|
190
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
191
|
+
return !!getParsedomElementByElement(item.element, 'img')
|
192
|
+
})
|
193
|
+
}
|
194
|
+
|
195
|
+
//选区是否含有视频
|
196
|
+
export const hasVideoInRange = vm => {
|
197
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
198
|
+
return !!getParsedomElementByElement(vm.editor.range.anchor.element, 'video')
|
199
|
+
}
|
200
|
+
return vm.dataRangeCaches.flatList.some(item => {
|
201
|
+
return !!getParsedomElementByElement(item.element, 'video')
|
202
|
+
})
|
203
|
+
}
|
204
|
+
|
205
|
+
//查询文本元素是否具有某个样式
|
206
|
+
export const queryTextStyle = (vm, name, value) => {
|
207
|
+
//起点和终点在一起
|
208
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
209
|
+
//如果是文本元素并且具有样式
|
210
|
+
if (vm.editor.range.anchor.element.isText() && vm.editor.range.anchor.element.hasStyles()) {
|
211
|
+
return queryHasValue(vm.editor.range.anchor.element.styles, name, value)
|
212
|
+
}
|
213
|
+
//不是文本元素或者没有样式直接返回
|
214
|
+
return false
|
215
|
+
}
|
216
|
+
//起点和终点不在一起获取选区中的文本元素
|
217
|
+
let result = vm.dataRangeCaches.flatList.filter(item => {
|
218
|
+
return item.element.isText()
|
219
|
+
})
|
220
|
+
//如果不包含文本元素直接返回false
|
221
|
+
if (result.length == 0) {
|
222
|
+
return false
|
223
|
+
}
|
224
|
+
//判断每个文本元素是否都具有该样式
|
225
|
+
let flag = result.every(item => {
|
226
|
+
//文本元素含有样式进一步判断
|
227
|
+
if (item.element.hasStyles()) {
|
228
|
+
return queryHasValue(item.element.styles, name, value)
|
229
|
+
}
|
230
|
+
//文本元素没有样式直接返回false
|
231
|
+
return false
|
232
|
+
})
|
233
|
+
return flag
|
234
|
+
}
|
235
|
+
|
236
|
+
//查询文本元素是否具有某个标记
|
237
|
+
export const queryTextMark = (vm, name, value) => {
|
238
|
+
//起点和终点在一起
|
239
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
240
|
+
//如果是文本元素并且具有标记
|
241
|
+
if (vm.editor.range.anchor.element.isText() && vm.editor.range.anchor.element.hasMarks()) {
|
242
|
+
return queryHasValue(vm.editor.range.anchor.element.marks, name, value)
|
243
|
+
}
|
244
|
+
//不是文本元素或者没有标记直接返回
|
245
|
+
return false
|
246
|
+
}
|
247
|
+
//起点和终点不在一起获取选区中的文本元素
|
248
|
+
let result = vm.dataRangeCaches.flatList.filter(item => {
|
249
|
+
return item.element.isText()
|
250
|
+
})
|
251
|
+
//如果不包含文本元素直接返回false
|
252
|
+
if (result.length == 0) {
|
253
|
+
return false
|
254
|
+
}
|
255
|
+
//判断每个文本元素是否都具有该标记
|
256
|
+
let flag = result.every(item => {
|
257
|
+
//文本元素含有标记进一步判断
|
258
|
+
if (item.element.hasMarks()) {
|
259
|
+
return queryHasValue(item.element.marks, name, value)
|
260
|
+
}
|
261
|
+
//文本元素没有标记直接返回false
|
262
|
+
return false
|
263
|
+
})
|
264
|
+
return flag
|
265
|
+
}
|
266
|
+
|
267
|
+
//获取链接文字内容,用于预置链接文字
|
268
|
+
export const getLinkText = vm => {
|
269
|
+
//存在选区的情况下预置链接文本值
|
270
|
+
let text = ''
|
271
|
+
vm.dataRangeCaches.flatList.forEach(item => {
|
272
|
+
if (item.element.isText()) {
|
273
|
+
if (item.offset) {
|
274
|
+
text += item.element.textContent.substring(item.offset[0], item.offset[1])
|
275
|
+
} else {
|
276
|
+
text += item.element.textContent || ''
|
277
|
+
}
|
278
|
+
}
|
279
|
+
})
|
280
|
+
return text
|
281
|
+
}
|
282
|
+
|
283
|
+
//获取光标选取内的扁平化元素数组(可能会分割文本元素导致stack变更,同时也会更新选取元素和光标位置)
|
284
|
+
export const getFlatElementsByRange = vm => {
|
285
|
+
//获取选区数据的长度
|
286
|
+
let length = vm.dataRangeCaches.flatList.length
|
287
|
+
//返回的元素数组
|
288
|
+
let elements = []
|
289
|
+
//遍历选区数据
|
290
|
+
for (let i = 0; i < length; i++) {
|
291
|
+
const item = vm.dataRangeCaches.flatList[i]
|
292
|
+
//如果存在offset那么一定是文本元素
|
293
|
+
if (item.offset) {
|
294
|
+
let selectEl = null
|
295
|
+
//文本元素前面一部分在光标范围内
|
296
|
+
if (item.offset[0] == 0 && item.offset[1] < item.element.textContent.length) {
|
297
|
+
const el = item.element.clone()
|
298
|
+
item.element.textContent = item.element.textContent.substring(0, item.offset[1])
|
299
|
+
el.textContent = el.textContent.substring(item.offset[1])
|
300
|
+
vm.editor.addElementAfter(el, item.element)
|
301
|
+
selectEl = item.element
|
302
|
+
}
|
303
|
+
//文本元素后面一部分在光标范围内
|
304
|
+
else if (item.offset[1] == item.element.textContent.length && item.offset[0] > 0) {
|
305
|
+
const el = item.element.clone()
|
306
|
+
item.element.textContent = item.element.textContent.substring(0, item.offset[0])
|
307
|
+
el.textContent = el.textContent.substring(item.offset[0])
|
308
|
+
vm.editor.addElementAfter(el, item.element)
|
309
|
+
selectEl = el
|
310
|
+
}
|
311
|
+
//文本元素的中间一部分在光标范围内
|
312
|
+
else if (item.offset[0] > 0 && item.offset[1] < item.element.textContent.length) {
|
313
|
+
const el = item.element.clone()
|
314
|
+
const el2 = item.element.clone()
|
315
|
+
item.element.textContent = item.element.textContent.substring(0, item.offset[0])
|
316
|
+
el.textContent = el.textContent.substring(item.offset[0], item.offset[1])
|
317
|
+
el2.textContent = el2.textContent.substring(item.offset[1])
|
318
|
+
vm.editor.addElementAfter(el, item.element)
|
319
|
+
vm.editor.addElementAfter(el2, el)
|
320
|
+
selectEl = el
|
321
|
+
}
|
322
|
+
//如果selectEl存在证明文本元素被分割了
|
323
|
+
if (selectEl) {
|
324
|
+
//如果i为0的话肯定是起点
|
325
|
+
if (i == 0) {
|
326
|
+
vm.editor.range.anchor.moveToStart(selectEl)
|
327
|
+
}
|
328
|
+
//如果i是最后一个序列的话肯定是终点
|
329
|
+
if (i == length - 1) {
|
330
|
+
vm.editor.range.focus.moveToEnd(selectEl)
|
331
|
+
}
|
332
|
+
elements.push(selectEl)
|
333
|
+
}
|
334
|
+
} else {
|
335
|
+
elements.push(item.element)
|
336
|
+
}
|
337
|
+
}
|
338
|
+
return elements
|
339
|
+
}
|
340
|
+
|
341
|
+
//将某个元素转为段落标签
|
342
|
+
export const elementToParagraph = function (element) {
|
343
|
+
element.marks = null
|
344
|
+
element.styles = null
|
345
|
+
element.parsedom = AlexElement.BLOCK_NODE
|
346
|
+
}
|
347
|
+
|
348
|
+
//其他元素转为有序或者无序列表
|
349
|
+
export const elementToList = function (element, ordered = false) {
|
350
|
+
//如果是列表则返回
|
351
|
+
if (isList(element, ordered)) {
|
352
|
+
return
|
353
|
+
}
|
354
|
+
//先转为段落
|
355
|
+
elementToParagraph(element)
|
356
|
+
//然后转为列表
|
357
|
+
element.parsedom = 'div'
|
358
|
+
if (!element.hasMarks()) {
|
359
|
+
element.marks = {}
|
360
|
+
}
|
361
|
+
element.marks['data-editify-list'] = ordered ? 'ol' : 'ul'
|
362
|
+
}
|
363
|
+
|
364
|
+
//其他元素转为任务列表
|
365
|
+
export const elementToTask = function (element) {
|
366
|
+
//如果是任务列表则返回
|
367
|
+
if (isTask(element)) {
|
368
|
+
return
|
369
|
+
}
|
370
|
+
//先转为段落
|
371
|
+
elementToParagraph(element)
|
372
|
+
//然后转为任务列表
|
373
|
+
element.parsedom = 'div'
|
374
|
+
if (!element.hasMarks()) {
|
375
|
+
element.marks = {}
|
376
|
+
}
|
377
|
+
element.marks['data-editify-task'] = 'uncheck'
|
378
|
+
}
|
379
|
+
|
380
|
+
//设置标题
|
381
|
+
export const setHeading = (vm, parsedom) => {
|
382
|
+
const values = getButtonOptionsConfig(vm.$editTrans, vm.$editLocale).heading.map(item => {
|
383
|
+
return item.value
|
384
|
+
})
|
385
|
+
if (!values.includes(parsedom)) {
|
386
|
+
throw new Error('The parameter supports only h1-h6 and p')
|
387
|
+
}
|
388
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
389
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
390
|
+
//先转为段落
|
391
|
+
elementToParagraph(block)
|
392
|
+
//设置标题
|
393
|
+
block.parsedom = parsedom
|
394
|
+
} else {
|
395
|
+
vm.dataRangeCaches.list.forEach(el => {
|
396
|
+
if (el.element.isBlock()) {
|
397
|
+
elementToParagraph(el.element)
|
398
|
+
el.element.parsedom = parsedom
|
399
|
+
} else {
|
400
|
+
const block = el.element.getBlock()
|
401
|
+
elementToParagraph(block)
|
402
|
+
block.parsedom = parsedom
|
403
|
+
}
|
404
|
+
})
|
405
|
+
}
|
406
|
+
}
|
407
|
+
|
408
|
+
//根级块元素或者内部块元素增加缩进
|
409
|
+
export const setIndentIncrease = vm => {
|
410
|
+
const fn = element => {
|
411
|
+
if (element.hasStyles()) {
|
412
|
+
if (element.styles.hasOwnProperty('text-indent')) {
|
413
|
+
let val = element.styles['text-indent']
|
414
|
+
if (val.endsWith('em')) {
|
415
|
+
val = parseFloat(val)
|
416
|
+
} else {
|
417
|
+
val = 0
|
418
|
+
}
|
419
|
+
element.styles['text-indent'] = `${val + 2}em`
|
420
|
+
} else {
|
421
|
+
element.styles['text-indent'] = '2em'
|
422
|
+
}
|
423
|
+
} else {
|
424
|
+
element.styles = {
|
425
|
+
'text-indent': '2em'
|
426
|
+
}
|
427
|
+
}
|
428
|
+
}
|
429
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
430
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
431
|
+
const inblock = vm.editor.range.anchor.element.getInblock()
|
432
|
+
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
433
|
+
fn(inblock)
|
434
|
+
} else if (!block.isPreStyle()) {
|
435
|
+
fn(block)
|
436
|
+
}
|
437
|
+
} else {
|
438
|
+
vm.dataRangeCaches.list.forEach(item => {
|
439
|
+
const block = item.element.getBlock()
|
440
|
+
const inblock = item.element.getInblock()
|
441
|
+
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
442
|
+
fn(inblock)
|
443
|
+
} else if (!block.isPreStyle()) {
|
444
|
+
fn(block)
|
445
|
+
}
|
446
|
+
})
|
447
|
+
}
|
448
|
+
}
|
449
|
+
|
450
|
+
//根级块元素或者内部块元素减少缩进
|
451
|
+
export const setIndentDecrease = vm => {
|
452
|
+
const fn = element => {
|
453
|
+
if (element.hasStyles() && element.styles.hasOwnProperty('text-indent')) {
|
454
|
+
let val = element.styles['text-indent']
|
455
|
+
if (val.endsWith('em')) {
|
456
|
+
val = parseFloat(val)
|
457
|
+
} else {
|
458
|
+
val = 0
|
459
|
+
}
|
460
|
+
element.styles['text-indent'] = `${val - 2 >= 0 ? val - 2 : 0}em`
|
461
|
+
}
|
462
|
+
}
|
463
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
464
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
465
|
+
const inblock = vm.editor.range.anchor.element.getInblock()
|
466
|
+
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
467
|
+
fn(inblock)
|
468
|
+
} else if (!block.isPreStyle()) {
|
469
|
+
fn(block)
|
470
|
+
}
|
471
|
+
} else {
|
472
|
+
vm.dataRangeCaches.list.forEach(item => {
|
473
|
+
const block = item.element.getBlock()
|
474
|
+
const inblock = item.element.getInblock()
|
475
|
+
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
476
|
+
fn(inblock)
|
477
|
+
} else if (!block.isPreStyle()) {
|
478
|
+
fn(block)
|
479
|
+
}
|
480
|
+
})
|
481
|
+
}
|
482
|
+
}
|
483
|
+
|
484
|
+
//插入或者取消引用
|
485
|
+
export const setQuote = vm => {
|
486
|
+
//是否都在引用里
|
487
|
+
const flag = isRangeInQuote(vm)
|
488
|
+
//起点和终点在一起
|
489
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
490
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
491
|
+
elementToParagraph(block)
|
492
|
+
if (!flag) {
|
493
|
+
block.parsedom = 'blockquote'
|
494
|
+
}
|
495
|
+
}
|
496
|
+
//起点和终点不在一起
|
497
|
+
else {
|
498
|
+
let blocks = []
|
499
|
+
vm.dataRangeCaches.list.forEach(item => {
|
500
|
+
const block = item.element.getBlock()
|
501
|
+
const exist = blocks.some(el => block.isEqual(el))
|
502
|
+
if (!exist) {
|
503
|
+
blocks.push(block)
|
504
|
+
}
|
505
|
+
})
|
506
|
+
blocks.forEach(block => {
|
507
|
+
elementToParagraph(block)
|
508
|
+
if (!flag) {
|
509
|
+
block.parsedom = 'blockquote'
|
510
|
+
}
|
511
|
+
})
|
512
|
+
}
|
513
|
+
}
|
514
|
+
|
515
|
+
//设置对齐方式,参数取值justify/left/right/center
|
516
|
+
export const setAlign = (vm, value) => {
|
517
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
518
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
519
|
+
const inblock = vm.editor.range.anchor.element.getInblock()
|
520
|
+
if (inblock) {
|
521
|
+
if (inblock.hasStyles()) {
|
522
|
+
inblock.styles['text-align'] = value
|
523
|
+
} else {
|
524
|
+
inblock.styles = {
|
525
|
+
'text-align': value
|
526
|
+
}
|
527
|
+
}
|
528
|
+
} else {
|
529
|
+
if (block.hasStyles()) {
|
530
|
+
block.styles['text-align'] = value
|
531
|
+
} else {
|
532
|
+
block.styles = {
|
533
|
+
'text-align': value
|
534
|
+
}
|
535
|
+
}
|
536
|
+
}
|
537
|
+
} else {
|
538
|
+
vm.dataRangeCaches.list.forEach(el => {
|
539
|
+
if (el.element.isBlock() || el.element.isInblock()) {
|
540
|
+
if (el.element.hasStyles()) {
|
541
|
+
el.element.styles['text-align'] = value
|
542
|
+
} else {
|
543
|
+
el.element.styles = {
|
544
|
+
'text-align': value
|
545
|
+
}
|
546
|
+
}
|
547
|
+
} else {
|
548
|
+
const block = el.element.getBlock()
|
549
|
+
const inblock = el.element.getInblock()
|
550
|
+
if (inblock) {
|
551
|
+
if (inblock.hasStyles()) {
|
552
|
+
inblock.styles['text-align'] = value
|
553
|
+
} else {
|
554
|
+
inblock.styles = {
|
555
|
+
'text-align': value
|
556
|
+
}
|
557
|
+
}
|
558
|
+
} else {
|
559
|
+
if (block.hasStyles()) {
|
560
|
+
block.styles['text-align'] = value
|
561
|
+
} else {
|
562
|
+
block.styles = {
|
563
|
+
'text-align': value
|
564
|
+
}
|
565
|
+
}
|
566
|
+
}
|
567
|
+
}
|
568
|
+
})
|
569
|
+
}
|
570
|
+
}
|
571
|
+
|
572
|
+
//插入或者取消 有序或者无序列表 ordered为true表示有序列表
|
573
|
+
export const setList = (vm, ordered) => {
|
574
|
+
//是否都在列表内
|
575
|
+
const flag = isRangeInList(vm, ordered)
|
576
|
+
//起点和终点在一起
|
577
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
578
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
579
|
+
if (flag) {
|
580
|
+
elementToParagraph(block)
|
581
|
+
} else {
|
582
|
+
elementToList(block, ordered)
|
583
|
+
}
|
584
|
+
}
|
585
|
+
//起点和终点不在一起
|
586
|
+
else {
|
587
|
+
let blocks = []
|
588
|
+
vm.dataRangeCaches.list.forEach(item => {
|
589
|
+
const block = item.element.getBlock()
|
590
|
+
const exist = blocks.some(el => block.isEqual(el))
|
591
|
+
if (!exist) {
|
592
|
+
blocks.push(block)
|
593
|
+
}
|
594
|
+
})
|
595
|
+
blocks.forEach(block => {
|
596
|
+
if (flag) {
|
597
|
+
elementToParagraph(block)
|
598
|
+
} else {
|
599
|
+
elementToList(block, ordered)
|
600
|
+
}
|
601
|
+
})
|
602
|
+
}
|
603
|
+
}
|
604
|
+
|
605
|
+
//插入或者取消任务列表
|
606
|
+
export const setTask = vm => {
|
607
|
+
//是否都在任务列表那
|
608
|
+
const flag = isRangeInTask(vm)
|
609
|
+
//起点和终点在一起
|
610
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
611
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
612
|
+
if (flag) {
|
613
|
+
elementToParagraph(block)
|
614
|
+
} else {
|
615
|
+
elementToTask(block)
|
616
|
+
}
|
617
|
+
}
|
618
|
+
//起点和终点不在一起
|
619
|
+
else {
|
620
|
+
let blocks = []
|
621
|
+
vm.dataRangeCaches.list.forEach(item => {
|
622
|
+
const block = item.element.getBlock()
|
623
|
+
const exist = blocks.some(el => block.isEqual(el))
|
624
|
+
if (!exist) {
|
625
|
+
blocks.push(block)
|
626
|
+
}
|
627
|
+
})
|
628
|
+
blocks.forEach(block => {
|
629
|
+
if (flag) {
|
630
|
+
elementToParagraph(block)
|
631
|
+
} else {
|
632
|
+
elementToTask(block)
|
633
|
+
}
|
634
|
+
})
|
635
|
+
}
|
636
|
+
}
|
637
|
+
|
638
|
+
//设置文本元素的样式,styles为{ 'font-weight':'bold' }这类格式
|
639
|
+
export const setTextStyle = (vm, styles) => {
|
640
|
+
//起点和终点在一起
|
641
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
642
|
+
//如果是空白文本元素直接设置样式
|
643
|
+
if (vm.editor.range.anchor.element.isSpaceText()) {
|
644
|
+
if (vm.editor.range.anchor.element.hasStyles()) {
|
645
|
+
Object.assign(vm.editor.range.anchor.element.styles, cloneData(styles))
|
646
|
+
} else {
|
647
|
+
vm.editor.range.anchor.element.styles = cloneData(styles)
|
648
|
+
}
|
649
|
+
}
|
650
|
+
//如果是文本元素
|
651
|
+
else if (vm.editor.range.anchor.element.isText()) {
|
652
|
+
//新建一个空白文本元素
|
653
|
+
const el = AlexElement.getSpaceElement()
|
654
|
+
//继承文本元素的样式和标记
|
655
|
+
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
656
|
+
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
657
|
+
//设置样式
|
658
|
+
if (el.hasStyles()) {
|
659
|
+
Object.assign(el.styles, cloneData(styles))
|
660
|
+
} else {
|
661
|
+
el.styles = cloneData(styles)
|
662
|
+
}
|
663
|
+
//插入空白文本元素
|
664
|
+
vm.editor.insertElement(el)
|
665
|
+
}
|
666
|
+
//如果是自闭合元素
|
667
|
+
else {
|
668
|
+
const el = AlexElement.getSpaceElement()
|
669
|
+
el.styles = cloneData(styles)
|
670
|
+
vm.editor.insertElement(el)
|
671
|
+
}
|
672
|
+
}
|
673
|
+
//不在同一个点
|
674
|
+
else {
|
675
|
+
const elements = getFlatElementsByRange(vm)
|
676
|
+
elements.forEach(ele => {
|
677
|
+
if (ele.isText()) {
|
678
|
+
if (ele.hasStyles()) {
|
679
|
+
Object.assign(ele.styles, cloneData(styles))
|
680
|
+
} else {
|
681
|
+
ele.styles = cloneData(styles)
|
682
|
+
}
|
683
|
+
}
|
684
|
+
})
|
685
|
+
}
|
686
|
+
}
|
687
|
+
|
688
|
+
//设置文本元素的标记,marks为{ 'class':'a' }这类格式
|
689
|
+
export const setTextMark = (vm, marks) => {
|
690
|
+
if (!DapCommon.isObject(marks)) {
|
691
|
+
throw new Error('The argument must be an object')
|
692
|
+
}
|
693
|
+
//起点和终点在一起
|
694
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
695
|
+
//如果是空白文本元素直接设置标记
|
696
|
+
if (vm.editor.range.anchor.element.isSpaceText()) {
|
697
|
+
if (vm.editor.range.anchor.element.hasMarks()) {
|
698
|
+
Object.assign(vm.editor.range.anchor.element.marks, cloneData(marks))
|
699
|
+
} else {
|
700
|
+
vm.editor.range.anchor.element.marks = cloneData(marks)
|
701
|
+
}
|
702
|
+
}
|
703
|
+
//如果是文本元素
|
704
|
+
else if (vm.editor.range.anchor.element.isText()) {
|
705
|
+
//新建一个空白文本元素
|
706
|
+
const el = AlexElement.getSpaceElement()
|
707
|
+
//继承文本元素的样式和标记
|
708
|
+
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
709
|
+
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
710
|
+
//设置标记
|
711
|
+
if (el.hasMarks()) {
|
712
|
+
Object.assign(el.marks, cloneData(marks))
|
713
|
+
} else {
|
714
|
+
el.marks = cloneData(marks)
|
715
|
+
}
|
716
|
+
//插入空白文本元素
|
717
|
+
vm.editor.insertElement(el)
|
718
|
+
}
|
719
|
+
//如果是自闭合元素
|
720
|
+
else {
|
721
|
+
const el = AlexElement.getSpaceElement()
|
722
|
+
el.marks = cloneData(marks)
|
723
|
+
vm.editor.insertElement(el)
|
724
|
+
}
|
725
|
+
}
|
726
|
+
//不在同一个点
|
727
|
+
else {
|
728
|
+
const elements = getFlatElementsByRange(vm)
|
729
|
+
elements.forEach(ele => {
|
730
|
+
if (ele.isText()) {
|
731
|
+
if (ele.hasMarks()) {
|
732
|
+
Object.assign(ele.marks, cloneData(marks))
|
733
|
+
} else {
|
734
|
+
ele.marks = cloneData(marks)
|
735
|
+
}
|
736
|
+
}
|
737
|
+
})
|
738
|
+
}
|
739
|
+
}
|
740
|
+
|
741
|
+
//移除文本元素的样式,styleNames是样式名称数组,如果不存在则移除全部样式
|
742
|
+
export const removeTextStyle = (vm, styleNames) => {
|
743
|
+
//移除样式的方法
|
744
|
+
const removeFn = el => {
|
745
|
+
//如果参数是数组,表示删除指定的样式
|
746
|
+
if (Array.isArray(styleNames)) {
|
747
|
+
if (el.hasStyles()) {
|
748
|
+
let styles = {}
|
749
|
+
Object.keys(el.styles).forEach(key => {
|
750
|
+
if (!styleNames.includes(key)) {
|
751
|
+
styles[key] = el.styles[key]
|
752
|
+
}
|
753
|
+
})
|
754
|
+
el.styles = styles
|
755
|
+
}
|
756
|
+
}
|
757
|
+
//如果没有参数,则表示删除所有的样式
|
758
|
+
else {
|
759
|
+
el.styles = null
|
760
|
+
}
|
761
|
+
}
|
762
|
+
//如果起点和终点在一起
|
763
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
764
|
+
//如果是空白文本元素直接移除样式
|
765
|
+
if (vm.editor.range.anchor.element.isSpaceText()) {
|
766
|
+
removeFn(vm.editor.range.anchor.element)
|
767
|
+
}
|
768
|
+
//如果是文本元素则新建一个空白文本元素
|
769
|
+
else if (vm.editor.range.anchor.element.isText()) {
|
770
|
+
const el = AlexElement.getSpaceElement()
|
771
|
+
//继承文本元素的样式和标记
|
772
|
+
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
773
|
+
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
774
|
+
//移除样式
|
775
|
+
removeFn(el)
|
776
|
+
//插入
|
777
|
+
vm.editor.insertElement(el)
|
778
|
+
}
|
779
|
+
}
|
780
|
+
//起点和终点不在一起
|
781
|
+
else {
|
782
|
+
const elements = getFlatElementsByRange(vm)
|
783
|
+
elements.forEach(ele => {
|
784
|
+
if (ele.isText()) {
|
785
|
+
removeFn(ele)
|
786
|
+
}
|
787
|
+
})
|
788
|
+
}
|
789
|
+
}
|
790
|
+
|
791
|
+
//移除文本元素的标记,markNames是标记名称数组,如果不存在则移除全部标记
|
792
|
+
export const removeTextMark = (vm, markNames) => {
|
793
|
+
//移除样式的方法
|
794
|
+
const removeFn = el => {
|
795
|
+
//如果参数是数组,表示删除指定的样式
|
796
|
+
if (Array.isArray(markNames)) {
|
797
|
+
if (el.hasMarks()) {
|
798
|
+
let marks = {}
|
799
|
+
Object.keys(el.marks).forEach(key => {
|
800
|
+
if (!markNames.includes(key)) {
|
801
|
+
marks[key] = el.marks[key]
|
802
|
+
}
|
803
|
+
})
|
804
|
+
el.marks = marks
|
805
|
+
}
|
806
|
+
}
|
807
|
+
//如果没有参数,则表示删除所有的样式
|
808
|
+
else {
|
809
|
+
el.marks = null
|
810
|
+
}
|
811
|
+
}
|
812
|
+
//如果起点和终点在一起
|
813
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
814
|
+
//如果是空白文本元素直接移除标记
|
815
|
+
if (vm.editor.range.anchor.element.isSpaceText()) {
|
816
|
+
removeFn(vm.editor.range.anchor.element)
|
817
|
+
}
|
818
|
+
//如果是文本元素则新建一个空白文本元素
|
819
|
+
else if (vm.editor.range.anchor.element.isText()) {
|
820
|
+
const el = AlexElement.getSpaceElement()
|
821
|
+
//继承文本元素的样式和标记
|
822
|
+
el.styles = cloneData(vm.editor.range.anchor.element.styles)
|
823
|
+
el.marks = cloneData(vm.editor.range.anchor.element.marks)
|
824
|
+
//移除标记
|
825
|
+
removeFn(el)
|
826
|
+
//插入
|
827
|
+
vm.editor.insertElement(el)
|
828
|
+
}
|
829
|
+
}
|
830
|
+
//起点和终点不在一起
|
831
|
+
else {
|
832
|
+
const elements = getFlatElementsByRange(vm)
|
833
|
+
elements.forEach(ele => {
|
834
|
+
if (ele.isText()) {
|
835
|
+
removeFn(ele)
|
836
|
+
}
|
837
|
+
})
|
838
|
+
}
|
839
|
+
}
|
840
|
+
|
841
|
+
//设置块元素或者根级块元素的行高
|
842
|
+
export const setLineHeight = (vm, value) => {
|
843
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
844
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
845
|
+
const inblock = vm.editor.range.anchor.element.getInblock()
|
846
|
+
if (inblock) {
|
847
|
+
if (inblock.hasStyles()) {
|
848
|
+
inblock.styles['line-height'] = value
|
849
|
+
} else {
|
850
|
+
inblock.styles = {
|
851
|
+
'line-height': value
|
852
|
+
}
|
853
|
+
}
|
854
|
+
} else {
|
855
|
+
if (block.hasStyles()) {
|
856
|
+
block.styles['line-height'] = value
|
857
|
+
} else {
|
858
|
+
block.styles = {
|
859
|
+
'line-height': value
|
860
|
+
}
|
861
|
+
}
|
862
|
+
}
|
863
|
+
} else {
|
864
|
+
vm.dataRangeCaches.list.forEach(el => {
|
865
|
+
if (el.element.isBlock() || el.element.isInblock()) {
|
866
|
+
if (el.element.hasStyles()) {
|
867
|
+
el.element.styles['line-height'] = value
|
868
|
+
} else {
|
869
|
+
el.element.styles = {
|
870
|
+
'line-height': value
|
871
|
+
}
|
872
|
+
}
|
873
|
+
} else {
|
874
|
+
const block = el.element.getBlock()
|
875
|
+
const inblock = el.element.getInblock()
|
876
|
+
if (inblock) {
|
877
|
+
if (inblock.hasStyles()) {
|
878
|
+
inblock.styles['line-height'] = value
|
879
|
+
} else {
|
880
|
+
inblock.styles = {
|
881
|
+
'line-height': value
|
882
|
+
}
|
883
|
+
}
|
884
|
+
} else {
|
885
|
+
if (block.hasStyles()) {
|
886
|
+
block.styles['line-height'] = value
|
887
|
+
} else {
|
888
|
+
block.styles = {
|
889
|
+
'line-height': value
|
890
|
+
}
|
891
|
+
}
|
892
|
+
}
|
893
|
+
}
|
894
|
+
})
|
895
|
+
}
|
896
|
+
}
|
897
|
+
|
898
|
+
//插入链接
|
899
|
+
export const insertLink = (vm, text, url, newOpen) => {
|
900
|
+
if (!text) {
|
901
|
+
text = url
|
902
|
+
}
|
903
|
+
const marks = {
|
904
|
+
href: url
|
905
|
+
}
|
906
|
+
if (newOpen) {
|
907
|
+
marks.target = '_blank'
|
908
|
+
}
|
909
|
+
const linkEle = new AlexElement('inline', 'a', marks, null, null)
|
910
|
+
const textEle = new AlexElement('text', null, null, null, text)
|
911
|
+
vm.editor.addElementTo(textEle, linkEle)
|
912
|
+
vm.editor.insertElement(linkEle)
|
913
|
+
}
|
914
|
+
|
915
|
+
//插入图片
|
916
|
+
export const insertImage = (vm, value) => {
|
917
|
+
const image = new AlexElement(
|
918
|
+
'closed',
|
919
|
+
'img',
|
920
|
+
{
|
921
|
+
src: value
|
922
|
+
},
|
923
|
+
null,
|
924
|
+
null
|
925
|
+
)
|
926
|
+
vm.editor.insertElement(image)
|
927
|
+
}
|
928
|
+
|
929
|
+
//插入视频
|
930
|
+
export const insertVideo = (vm, value) => {
|
931
|
+
const video = new AlexElement(
|
932
|
+
'closed',
|
933
|
+
'video',
|
934
|
+
{
|
935
|
+
src: value
|
936
|
+
},
|
937
|
+
null,
|
938
|
+
null
|
939
|
+
)
|
940
|
+
vm.editor.insertElement(video)
|
941
|
+
const leftSpace = AlexElement.getSpaceElement()
|
942
|
+
const rightSpace = AlexElement.getSpaceElement()
|
943
|
+
vm.editor.addElementAfter(rightSpace, video)
|
944
|
+
vm.editor.addElementBefore(leftSpace, video)
|
945
|
+
vm.editor.range.anchor.moveToEnd(rightSpace)
|
946
|
+
vm.editor.range.focus.moveToEnd(rightSpace)
|
947
|
+
}
|
948
|
+
|
949
|
+
//插入表格
|
950
|
+
export const insertTable = (vm, rowLength, colLength) => {
|
951
|
+
const table = new AlexElement('block', 'table', null, null, null)
|
952
|
+
const tbody = new AlexElement('inblock', 'tbody', null, null, null)
|
953
|
+
vm.editor.addElementTo(tbody, table)
|
954
|
+
for (let i = 0; i < rowLength; i++) {
|
955
|
+
const row = new AlexElement('inblock', 'tr', null, null, null)
|
956
|
+
for (let j = 0; j < colLength; j++) {
|
957
|
+
const column = new AlexElement('inblock', 'td', null, null, null)
|
958
|
+
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
959
|
+
vm.editor.addElementTo(breakEl, column)
|
960
|
+
vm.editor.addElementTo(column, row)
|
961
|
+
}
|
962
|
+
vm.editor.addElementTo(row, tbody)
|
963
|
+
}
|
964
|
+
vm.editor.insertElement(table)
|
965
|
+
//在表格后创建一个段落
|
966
|
+
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
967
|
+
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
968
|
+
vm.editor.addElementTo(breakEl, paragraph)
|
969
|
+
vm.editor.addElementAfter(paragraph, table)
|
970
|
+
vm.editor.range.anchor.moveToStart(tbody)
|
971
|
+
vm.editor.range.focus.moveToStart(tbody)
|
972
|
+
}
|
973
|
+
|
974
|
+
//插入或者取消代码块
|
975
|
+
export const insertCodeBlock = vm => {
|
976
|
+
const pre = getCurrentParsedomElement(vm, 'pre')
|
977
|
+
if (pre) {
|
978
|
+
let content = ''
|
979
|
+
AlexElement.flatElements(pre.children)
|
980
|
+
.filter(item => {
|
981
|
+
return item.isText()
|
982
|
+
})
|
983
|
+
.forEach(item => {
|
984
|
+
content += item.textContent
|
985
|
+
})
|
986
|
+
const splits = content.split('\n')
|
987
|
+
splits.forEach(item => {
|
988
|
+
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
989
|
+
const text = new AlexElement('text', null, null, null, item)
|
990
|
+
vm.editor.addElementTo(text, paragraph)
|
991
|
+
vm.editor.addElementBefore(paragraph, pre)
|
992
|
+
})
|
993
|
+
pre.toEmpty()
|
994
|
+
} else {
|
995
|
+
//起点和终点在一起
|
996
|
+
if (vm.editor.range.anchor.isEqual(vm.editor.range.focus)) {
|
997
|
+
const block = vm.editor.range.anchor.element.getBlock()
|
998
|
+
elementToParagraph(block)
|
999
|
+
block.parsedom = 'pre'
|
1000
|
+
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1001
|
+
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1002
|
+
vm.editor.addElementTo(breakEl, paragraph)
|
1003
|
+
vm.editor.addElementAfter(paragraph, block)
|
1004
|
+
}
|
1005
|
+
//起点和终点不在一起
|
1006
|
+
else {
|
1007
|
+
vm.editor.range.anchor.moveToStart(vm.dataRangeCaches.list[0].element.getBlock())
|
1008
|
+
vm.editor.range.focus.moveToEnd(vm.dataRangeCaches.list[vm.dataRangeCaches.list.length - 1].element.getBlock())
|
1009
|
+
const res = vm.dataRangeCaches.flatList.filter(el => el.element.isText())
|
1010
|
+
const obj = {}
|
1011
|
+
res.forEach(el => {
|
1012
|
+
if (obj[el.element.getBlock().key]) {
|
1013
|
+
obj[el.element.getBlock().key].push(el.element.clone())
|
1014
|
+
} else {
|
1015
|
+
obj[el.element.getBlock().key] = [el.element.clone()]
|
1016
|
+
}
|
1017
|
+
})
|
1018
|
+
const pre = new AlexElement('block', 'pre', null, null, null)
|
1019
|
+
Object.keys(obj).forEach((key, index) => {
|
1020
|
+
if (index > 0) {
|
1021
|
+
const text = new AlexElement('text', null, null, null, '\n')
|
1022
|
+
if (pre.hasChildren()) {
|
1023
|
+
vm.editor.addElementTo(text, pre, pre.children.length)
|
1024
|
+
} else {
|
1025
|
+
vm.editor.addElementTo(text, pre)
|
1026
|
+
}
|
1027
|
+
}
|
1028
|
+
obj[key].forEach(el => {
|
1029
|
+
if (pre.hasChildren()) {
|
1030
|
+
vm.editor.addElementTo(el, pre, pre.children.length)
|
1031
|
+
} else {
|
1032
|
+
vm.editor.addElementTo(el, pre)
|
1033
|
+
}
|
1034
|
+
})
|
1035
|
+
})
|
1036
|
+
vm.editor.delete()
|
1037
|
+
vm.editor.insertElement(pre)
|
1038
|
+
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1039
|
+
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1040
|
+
vm.editor.addElementTo(breakEl, paragraph)
|
1041
|
+
vm.editor.addElementAfter(paragraph, pre)
|
1042
|
+
}
|
1043
|
+
}
|
1044
|
+
}
|