vue-editify 0.1.10 → 0.1.13

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