vue-editify 0.2.17 → 0.2.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. package/examples/App.vue +289 -13
  2. package/lib/components/colors/colors.vue.d.ts +9 -0
  3. package/lib/components/colors/props.d.ts +4 -0
  4. package/lib/core/function.d.ts +120 -45
  5. package/lib/core/rule.d.ts +23 -17
  6. package/lib/core/tool.d.ts +1 -13
  7. package/lib/editify/editify.vue.d.ts +10 -1
  8. package/lib/editify/props.d.ts +1 -1
  9. package/lib/editify/toolbar/props.d.ts +1 -1
  10. package/lib/editify/toolbar/toolbar.vue.d.ts +3 -3
  11. package/lib/editify.es.js +13640 -13799
  12. package/lib/editify.umd.js +2 -2
  13. package/lib/feature/align.d.ts +0 -14
  14. package/lib/feature/heading.d.ts +0 -14
  15. package/lib/feature/lineHeight.d.ts +0 -14
  16. package/lib/feature/orderList.d.ts +1 -3
  17. package/lib/feature/task.d.ts +0 -14
  18. package/lib/feature/unorderList.d.ts +1 -3
  19. package/lib/index.d.ts +12 -3
  20. package/package.json +2 -2
  21. package/src/components/button/button.vue +3 -3
  22. package/src/components/checkbox/checkbox.vue +1 -1
  23. package/src/components/colors/colors.vue +4 -4
  24. package/src/components/colors/props.ts +6 -1
  25. package/src/components/insertAttachment/insertAttachment.vue +1 -1
  26. package/src/components/insertImage/insertImage.vue +1 -1
  27. package/src/components/insertLink/insertLink.vue +1 -1
  28. package/src/components/insertVideo/insertVideo.vue +1 -1
  29. package/src/components/layer/layer.vue +9 -3
  30. package/src/components/tooltip/tooltip.vue +1 -1
  31. package/src/components/updateLink/updateLink.vue +1 -1
  32. package/src/core/function.ts +961 -475
  33. package/src/core/rule.ts +85 -367
  34. package/src/core/tool.ts +8 -114
  35. package/src/editify/editify.less +88 -14
  36. package/src/editify/editify.vue +117 -65
  37. package/src/editify/props.ts +1 -1
  38. package/src/editify/toolbar/props.ts +2 -2
  39. package/src/editify/toolbar/toolbar.vue +12 -12
  40. package/src/feature/align.ts +1 -61
  41. package/src/feature/attachment.ts +13 -26
  42. package/src/feature/backColor.ts +1 -0
  43. package/src/feature/foreColor.ts +1 -0
  44. package/src/feature/heading.ts +2 -73
  45. package/src/feature/infoBlock.ts +4 -35
  46. package/src/feature/lineHeight.ts +1 -77
  47. package/src/feature/mathformula.ts +3 -50
  48. package/src/feature/orderList.ts +166 -35
  49. package/src/feature/panel.ts +4 -49
  50. package/src/feature/sub.ts +1 -1
  51. package/src/feature/super.ts +1 -1
  52. package/src/feature/task.ts +1 -55
  53. package/src/feature/unorderList.ts +106 -35
  54. package/src/feature/video.ts +1 -1
  55. package/src/icon/iconfont.css +40 -0
  56. package/src/icon/iconfont.ttf +0 -0
  57. package/src/icon/iconfont.woff +0 -0
  58. package/src/index.ts +14 -8
  59. package/src/locale/en_US.ts +112 -110
  60. package/src/locale/zh_CN.ts +11 -9
package/src/core/tool.ts CHANGED
@@ -102,11 +102,6 @@ export type CodeBlockToolbarType = {
102
102
  }
103
103
 
104
104
  export type TextToolbarType = {
105
- heading?: MenuDisplayButtonType
106
- align?: MenuSelectButtonType
107
- orderList?: MenuButtonType
108
- unorderList?: MenuButtonType
109
- task?: MenuButtonType
110
105
  bold?: MenuButtonType
111
106
  italic?: MenuButtonType
112
107
  strikethrough?: MenuButtonType
@@ -116,7 +111,6 @@ export type TextToolbarType = {
116
111
  sub?: MenuButtonType
117
112
  fontSize?: MenuDisplayButtonType
118
113
  fontFamily?: MenuDisplayButtonType
119
- lineHeight?: MenuDisplayButtonType
120
114
  foreColor?: MenuSelectButtonType
121
115
  backColor?: MenuSelectButtonType
122
116
  formatClear?: MenuButtonType
@@ -288,18 +282,6 @@ export const queryHasValue = (obj: ObjectType, name: string, value?: string | nu
288
282
  return ownValue == value
289
283
  }
290
284
 
291
- /**
292
- * 深拷贝函数
293
- * @param data
294
- * @returns
295
- */
296
- export const cloneData = (data: any) => {
297
- if (DapCommon.isObject(data) || Array.isArray(data)) {
298
- return JSON.parse(JSON.stringify(data))
299
- }
300
- return data
301
- }
302
-
303
285
  /**
304
286
  * 获取菜单按钮列表数据配置
305
287
  * @param editTrans
@@ -506,7 +488,7 @@ export const getButtonOptionsConfig = (editTrans: (key: string) => any): ButtonO
506
488
  * @param editLocale
507
489
  * @returns
508
490
  */
509
- export const getToolbarConfig = (editTrans: (key: string) => any, editLocale: LocaleType): ToolbarConfigType => {
491
+ export const getToolbarConfig = (editTrans: (key: string) => any): ToolbarConfigType => {
510
492
  return {
511
493
  //是否使用工具条
512
494
  use: true,
@@ -542,75 +524,6 @@ export const getToolbarConfig = (editTrans: (key: string) => any, editLocale: Lo
542
524
  },
543
525
  //文本工具条配置
544
526
  text: {
545
- //标题
546
- heading: {
547
- //是否显示此工具
548
- show: false,
549
- //是否禁用此工具
550
- disabled: false,
551
- //列表配置
552
- options: getButtonOptionsConfig(editTrans).heading,
553
- //按钮默认显示的值
554
- defaultValue: 'p',
555
- //浮层宽度
556
- width: editLocale == 'zh_CN' ? 130 : 150,
557
- //浮层最大高度
558
- maxHeight: '',
559
- //左侧边框是否显示
560
- leftBorder: false,
561
- //右侧边框是否显示
562
- rightBorder: false
563
- },
564
- //对齐方式
565
- align: {
566
- //是否显示此工具
567
- show: false,
568
- //是否禁用此工具
569
- disabled: false,
570
- //列表配置
571
- options: getButtonOptionsConfig(editTrans).align,
572
- //浮层宽度
573
- width: editLocale == 'zh_CN' ? 110 : 130,
574
- //浮层最大高度
575
- maxHeight: '',
576
- //左侧边框是否显示
577
- leftBorder: false,
578
- //右侧边框是否显示
579
- rightBorder: false
580
- },
581
- //有序列表
582
- orderList: {
583
- //是否显示此工具
584
- show: false,
585
- //是否禁用此工具
586
- disabled: false,
587
- //左侧边框是否显示
588
- leftBorder: false,
589
- //右侧边框是否显示
590
- rightBorder: false
591
- },
592
- //无序列表
593
- unorderList: {
594
- //是否显示此工具
595
- show: false,
596
- //是否禁用此工具
597
- disabled: false,
598
- //左侧边框是否显示
599
- leftBorder: false,
600
- //右侧边框是否显示
601
- rightBorder: false
602
- },
603
- //任务列表
604
- task: {
605
- //是否显示此工具
606
- show: false,
607
- //是否禁用此工具
608
- disabled: false,
609
- //左侧边框是否显示
610
- leftBorder: false,
611
- //右侧边框是否显示
612
- rightBorder: false
613
- },
614
527
  //粗体
615
528
  bold: {
616
529
  //是否显示此工具
@@ -726,25 +639,6 @@ export const getToolbarConfig = (editTrans: (key: string) => any, editLocale: Lo
726
639
  //右侧边框是否显示
727
640
  rightBorder: false
728
641
  },
729
- //行高
730
- lineHeight: {
731
- //是否显示此工具
732
- show: false,
733
- //是否禁用此工具
734
- disabled: false,
735
- //列表配置
736
- options: getButtonOptionsConfig(editTrans).lineHeight,
737
- //按钮默认显示的值
738
- defaultValue: '',
739
- //浮层宽度
740
- width: 90,
741
- //浮层最大高度
742
- maxHeight: '',
743
- //左侧边框是否显示
744
- leftBorder: false,
745
- //右侧边框是否显示
746
- rightBorder: false
747
- },
748
642
  //前景色
749
643
  foreColor: {
750
644
  //是否显示此工具
@@ -754,7 +648,7 @@ export const getToolbarConfig = (editTrans: (key: string) => any, editLocale: Lo
754
648
  //列表配置
755
649
  options: getButtonOptionsConfig(editTrans).foreColor,
756
650
  //左侧边框是否显示
757
- leftBorder: false,
651
+ leftBorder: true,
758
652
  //右侧边框是否显示
759
653
  rightBorder: false
760
654
  },
@@ -832,12 +726,12 @@ export const getMenuConfig = (editTrans: (key: string) => any, editLocale: Local
832
726
  video: 25,
833
727
  table: 26,
834
728
  codeBlock: 27,
835
- sourceView: 28,
836
- fullScreen: 29,
837
- attachment: 30,
838
- mathformula: 31,
839
- panel: 32,
840
- infoBlock: 33
729
+ attachment: 28,
730
+ mathformula: 29,
731
+ panel: 30,
732
+ infoBlock: 31,
733
+ sourceView: 32,
734
+ fullScreen: 33
841
735
  },
842
736
  //撤销按钮配置
843
737
  undo: {
@@ -136,23 +136,92 @@
136
136
  :deep(h6) {
137
137
  font-size: 16px;
138
138
  }
139
+
140
+ //不是有序列表元素则重置后面的有序列表序列
141
+ :deep(:not(div[data-editify-list='ol'])) + div[data-editify-list='ol'] {
142
+ counter-reset: item 0;
143
+ }
144
+
139
145
  //有序列表样式
140
146
  :deep(div[data-editify-list='ol']) {
141
147
  margin-bottom: 15px;
142
148
 
149
+ //第一个元素重置序列
150
+ &:first-of-type {
151
+ counter-reset: item 0;
152
+ }
153
+
143
154
  &::before {
144
- content: attr(data-editify-value) '.';
155
+ counter-increment: item;
156
+ content: counter(item) '.';
145
157
  margin-right: 10px;
146
158
  }
159
+
160
+ &[data-editify-list-style='decimal'] {
161
+ &::before {
162
+ content: counter(item, decimal) '.';
163
+ }
164
+ }
165
+ &[data-editify-list-style='decimal-leading-zero'] {
166
+ &::before {
167
+ content: counter(item, decimal-leading-zero) '.';
168
+ }
169
+ }
170
+ &[data-editify-list-style='lower-roman'] {
171
+ &::before {
172
+ content: counter(item, lower-roman) '.';
173
+ }
174
+ }
175
+ &[data-editify-list-style='upper-roman'] {
176
+ &::before {
177
+ content: counter(item, upper-roman) '.';
178
+ }
179
+ }
180
+ &[data-editify-list-style='lower-alpha'] {
181
+ &::before {
182
+ content: counter(item, lower-alpha) '.';
183
+ }
184
+ }
185
+ &[data-editify-list-style='upper-alpha'] {
186
+ &::before {
187
+ content: counter(item, upper-alpha) '.';
188
+ }
189
+ }
190
+ &[data-editify-list-style='lower-greek'] {
191
+ &::before {
192
+ content: counter(item, lower-greek) '.';
193
+ }
194
+ }
195
+ &[data-editify-list-style='cjk-ideographic'] {
196
+ &::before {
197
+ content: counter(item, cjk-ideographic) '.';
198
+ }
199
+ }
147
200
  }
148
201
  //无序列表样式
149
202
  :deep(div[data-editify-list='ul']) {
150
203
  margin-bottom: 15px;
151
204
 
152
205
  &::before {
153
- content: '\2022';
206
+ content: counter(item, disc);
154
207
  margin-right: 10px;
155
208
  }
209
+
210
+ &[data-editify-list-style='disc'] {
211
+ &::before {
212
+ content: counter(item, disc);
213
+ }
214
+ }
215
+ &[data-editify-list-style='circle'] {
216
+ &::before {
217
+ content: counter(item, circle);
218
+ }
219
+ }
220
+ &[data-editify-list-style='square'] {
221
+ &::before {
222
+ content: counter(item, square);
223
+ }
224
+ }
156
225
  }
157
226
  //代码样式
158
227
  :deep([data-editify-code]) {
@@ -309,15 +378,13 @@
309
378
  padding-left: 26px;
310
379
  font-size: var(--editify-font-size);
311
380
  color: var(--editify-font-color-dark);
312
- transition: all 300ms;
313
381
 
314
382
  &::before {
315
383
  display: block;
316
- width: 16px;
317
- height: 16px;
384
+ width: 14px;
385
+ height: 14px;
318
386
  border-radius: 2px;
319
387
  border: 1px solid var(--editify-font-color-light);
320
- transition: all 300ms;
321
388
  box-sizing: border-box;
322
389
  user-select: none;
323
390
  content: '';
@@ -332,29 +399,32 @@
332
399
  &::after {
333
400
  display: inline-block;
334
401
  width: 10px;
335
- height: 6px;
402
+ height: 5px;
336
403
  position: absolute;
337
404
  content: '';
338
- left: 3px;
405
+ left: 2px;
339
406
  top: 50%;
340
- margin-top: -2px;
341
- border: 1px solid var(--editify-font-color-light);
407
+ margin-top: -1px;
408
+ border: 2px solid transparent;
342
409
  border-top: none;
343
410
  border-right: none;
344
411
  transform: translateY(-50%) rotate(-45deg);
345
412
  transform-origin: center;
346
- box-sizing: border-box;
347
413
  z-index: 2;
348
414
  cursor: pointer;
349
- opacity: 0;
350
- transition: all 300ms;
351
415
  }
352
416
 
353
417
  &[data-editify-task='checked'] {
354
418
  text-decoration: line-through;
355
419
  color: var(--editify-font-color-light);
420
+
421
+ &::before {
422
+ background-color: var(--editify-font-color-disabled);
423
+ border-color: var(--editify-font-color-disabled);
424
+ }
425
+
356
426
  &::after {
357
- opacity: 1;
427
+ border-color: #fff;
358
428
  }
359
429
  }
360
430
  }
@@ -428,6 +498,10 @@
428
498
  font-size: 18px;
429
499
  border-bottom: 1px solid var(--editify-border-color);
430
500
  padding-bottom: 8px;
501
+
502
+ &:empty {
503
+ background-color: #000;
504
+ }
431
505
  }
432
506
  }
433
507
  }
@@ -21,10 +21,10 @@
21
21
  <script setup lang="ts">
22
22
  import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
23
23
  import { AlexEditor, AlexElement, AlexElementRangeType, AlexElementsRangeType } from 'alex-editor'
24
- import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor } from 'dap-util'
25
- import { mergeObject, getToolbarConfig, getMenuConfig, MenuConfigType, ObjectType, ToolbarConfigType, clickIsOut, cloneData } from '@/core/tool'
26
- import { parseList, orderdListHandle, commonElementHandle, tableThTdHandle, tableFormatHandle, tableRangeMergedHandle, preHandle, specialInblockHandle, attachmentHandle, mathformulaHandle, infoBlockHandle } from '@/core/rule'
27
- import { elementToParagraph, getMatchElementByRange, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange, elementIsTask, elementIsAttachment, elementIsList, elementIsMathformula, getMathformulaByElement, elementIsPanel, elementIsInfoBlock } from '@/core/function'
24
+ import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor, common as DapCommon } from 'dap-util'
25
+ import { mergeObject, getToolbarConfig, getMenuConfig, MenuConfigType, ObjectType, ToolbarConfigType, clickIsOut } from '@/core/tool'
26
+ import { listHandle, imageHandle, videoHandle, separatorHandle, linkHandle, codeHandle, tableHandle, preHandle, attachmentHandle, mathformulaHandle, infoBlockHandle, specialInblockHandle } from '@/core/rule'
27
+ import { elementToParagraph, getMatchElementByRange, elementIsTask, elementIsAttachment, elementIsList, elementIsMathformula, getMathformulaByElement, elementIsPanel, elementIsInfoBlock, getMatchElementByElement } from '@/core/function'
28
28
  import { trans } from '@/locale'
29
29
  import { LanguagesItemType } from '@/hljs'
30
30
  import { extraKeepTagsForMathformula } from '@/feature/mathformula'
@@ -125,7 +125,7 @@ const showBorder = computed<boolean>(() => {
125
125
  })
126
126
  //最终生效的工具栏配置
127
127
  const toolbarConfig = computed<ToolbarConfigType>(() => {
128
- return mergeObject(getToolbarConfig($editTrans, props.locale), props.toolbar || {}) as ToolbarConfigType
128
+ return mergeObject(getToolbarConfig($editTrans), props.toolbar || {}) as ToolbarConfigType
129
129
  })
130
130
  //最终生效的菜单栏配置
131
131
  const menuConfig = computed<MenuConfigType>(() => {
@@ -163,9 +163,7 @@ const handleToolbar = () => {
163
163
  }
164
164
  hideToolbar()
165
165
  nextTick(() => {
166
- const table = getMatchElementByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
167
166
  const codeBlock = getMatchElementByRange(editor.value!, dataRangeCaches.value, { parsedom: 'pre' })
168
- const link = getMatchElementByRange(editor.value!, dataRangeCaches.value, { parsedom: 'a' })
169
167
  const image = getMatchElementByRange(editor.value!, dataRangeCaches.value, { parsedom: 'img' })
170
168
  const video = getMatchElementByRange(editor.value!, dataRangeCaches.value, { parsedom: 'video' })
171
169
 
@@ -189,26 +187,6 @@ const handleToolbar = () => {
189
187
  toolbarOptions.value.show = true
190
188
  }
191
189
  }
192
- //显示链接工具条
193
- else if (link) {
194
- toolbarOptions.value.type = 'link'
195
- toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${link.key}"]`
196
- if (toolbarOptions.value.show) {
197
- toolbarRef.value!.layerRef!.setPosition()
198
- } else {
199
- toolbarOptions.value.show = true
200
- }
201
- }
202
- //显示表格工具条
203
- else if (table) {
204
- toolbarOptions.value.type = 'table'
205
- toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${table.key}"]`
206
- if (toolbarOptions.value.show) {
207
- toolbarRef.value!.layerRef!.setPosition()
208
- } else {
209
- toolbarOptions.value.show = true
210
- }
211
- }
212
190
  //显示代码块工具条
213
191
  else if (codeBlock) {
214
192
  toolbarOptions.value.type = 'codeBlock'
@@ -219,10 +197,11 @@ const handleToolbar = () => {
219
197
  toolbarOptions.value.show = true
220
198
  }
221
199
  }
222
- //显示文本工具条
200
+ //以下是选区时显示文本工具条,非选区时显示其他工具条的情况
223
201
  else {
224
202
  const result = dataRangeCaches.value.flatList.filter((item: AlexElementRangeType) => item.element.isText())
225
- if (result.length && !hasTableInRange(editor.value!, dataRangeCaches.value) && !hasPreInRange(editor.value!, dataRangeCaches.value) && !hasLinkInRange(editor.value!, dataRangeCaches.value) && !hasImageInRange(editor.value!, dataRangeCaches.value) && !hasVideoInRange(editor.value!, dataRangeCaches.value)) {
203
+ //显示文本工具条
204
+ if (result.length) {
226
205
  toolbarOptions.value.type = 'text'
227
206
  if (toolbarOptions.value.show) {
228
207
  toolbarRef.value!.layerRef!.setPosition()
@@ -230,6 +209,63 @@ const handleToolbar = () => {
230
209
  toolbarOptions.value.show = true
231
210
  }
232
211
  }
212
+ //显示其他工具条
213
+ else {
214
+ const table = getMatchElementByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
215
+ const link = getMatchElementByRange(editor.value!, dataRangeCaches.value, { parsedom: 'a' })
216
+ const orderList = getMatchElementByRange(editor.value!, dataRangeCaches.value, {
217
+ parsedom: 'div',
218
+ marks: {
219
+ 'data-editify-list': 'ol'
220
+ }
221
+ })
222
+ const unorderList = getMatchElementByRange(editor.value!, dataRangeCaches.value, {
223
+ parsedom: 'div',
224
+ marks: {
225
+ 'data-editify-list': 'ul'
226
+ }
227
+ })
228
+ //显示链接工具条
229
+ if (link) {
230
+ toolbarOptions.value.type = 'link'
231
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${link.key}"]`
232
+ if (toolbarOptions.value.show) {
233
+ toolbarRef.value!.layerRef!.setPosition()
234
+ } else {
235
+ toolbarOptions.value.show = true
236
+ }
237
+ }
238
+ //显示表格工具条
239
+ else if (table) {
240
+ toolbarOptions.value.type = 'table'
241
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${table.key}"]`
242
+ if (toolbarOptions.value.show) {
243
+ toolbarRef.value!.layerRef!.setPosition()
244
+ } else {
245
+ toolbarOptions.value.show = true
246
+ }
247
+ }
248
+ //显示有序列表工具条
249
+ else if (orderList) {
250
+ toolbarOptions.value.type = 'orderList'
251
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${orderList.key}"]`
252
+ if (toolbarOptions.value.show) {
253
+ toolbarRef.value!.layerRef!.setPosition()
254
+ } else {
255
+ toolbarOptions.value.show = true
256
+ }
257
+ }
258
+ //显示无序列表工具条
259
+ else if (unorderList) {
260
+ toolbarOptions.value.type = 'unorderList'
261
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${unorderList.key}"]`
262
+ if (toolbarOptions.value.show) {
263
+ toolbarRef.value!.layerRef!.setPosition()
264
+ } else {
265
+ toolbarOptions.value.show = true
266
+ }
267
+ }
268
+ }
233
269
  }
234
270
  })
235
271
  }
@@ -241,28 +277,28 @@ const createEditor = () => {
241
277
  disabled: isDisabled.value,
242
278
  renderRules: [
243
279
  el => {
244
- parseList(editor.value!, el)
280
+ listHandle(editor.value!, el)
245
281
  },
246
282
  el => {
247
- orderdListHandle(editor.value!, el)
283
+ imageHandle(editor.value!, el)
248
284
  },
249
285
  el => {
250
- commonElementHandle(editor.value!, el)
286
+ videoHandle(editor.value!, el)
251
287
  },
252
288
  el => {
253
- tableThTdHandle(editor.value!, el)
289
+ separatorHandle(editor.value!, el)
254
290
  },
255
291
  el => {
256
- tableFormatHandle(editor.value!, el)
292
+ linkHandle(editor.value!, el)
257
293
  },
258
294
  el => {
259
- tableRangeMergedHandle(editor.value!, el)
295
+ codeHandle(editor.value!, el)
260
296
  },
261
297
  el => {
262
- preHandle(editor.value!, el, !!(toolbarConfig.value?.use && toolbarConfig.value?.codeBlock?.languages?.show), toolbarConfig.value?.codeBlock?.languages?.options as (string | LanguagesItemType)[])
298
+ tableHandle(editor.value!, el)
263
299
  },
264
300
  el => {
265
- specialInblockHandle(editor.value!, el)
301
+ preHandle(editor.value!, el, !!(toolbarConfig.value?.use && toolbarConfig.value?.codeBlock?.languages?.show), toolbarConfig.value?.codeBlock?.languages?.options as (string | LanguagesItemType)[])
266
302
  },
267
303
  el => {
268
304
  attachmentHandle(editor.value!, el, $editTrans)
@@ -273,6 +309,9 @@ const createEditor = () => {
273
309
  el => {
274
310
  infoBlockHandle(editor.value!, el, props.color)
275
311
  },
312
+ el => {
313
+ specialInblockHandle(editor.value!, el)
314
+ },
276
315
  ...props.renderRules
277
316
  ],
278
317
  extraKeepTags: [...extraKeepTagsForMathformula, ...props.extraKeepTags],
@@ -473,7 +512,7 @@ const documentClick = (e: Event) => {
473
512
  if (key) {
474
513
  const element = editor.value!.getElementByKey(key)!
475
514
  //如果是任务列表元素
476
- if (elementIsTask(element)) {
515
+ if (element && elementIsTask(element)) {
477
516
  const rect = DapElement.getElementBounding(elm)
478
517
  //在复选框范围内
479
518
  if (event.pageX >= Math.abs(rect.left) && event.pageX <= Math.abs(rect.left + 16) && event.pageY >= Math.abs(rect.top + elm.offsetHeight / 2 - 8) && event.pageY <= Math.abs(rect.top + elm.offsetHeight / 2 + 8)) {
@@ -499,7 +538,8 @@ const documentClick = (e: Event) => {
499
538
  }
500
539
  //重新定义编辑器粘贴html
501
540
  const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
502
- AlexElement.flatElements(elements).forEach(el => {
541
+ const flatElements = AlexElement.flatElements(elements)
542
+ flatElements.forEach(el => {
503
543
  if (!el.isText()) {
504
544
  let marks: ObjectType = {}
505
545
  let styles: ObjectType = {}
@@ -552,10 +592,7 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
552
592
  //有序和无序列表属性保留
553
593
  if (elementIsList(el, true) || elementIsList(el, false)) {
554
594
  marks['data-editify-list'] = el.marks!['data-editify-list']
555
- //有序列表保留序列号标记
556
- if (el.marks!['data-editify-value']) {
557
- marks['data-editify-value'] = el.marks!['data-editify-value']
558
- }
595
+ marks['data-editify-list-style'] = el.marks!['data-editify-list-style']
559
596
  }
560
597
  //行内代码属性保留
561
598
  if (el.parsedom == AlexElement.TEXT_NODE && el.marks!['data-editify-code']) {
@@ -590,7 +627,7 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
590
627
  }
591
628
  //数学公式内的属性全部保留
592
629
  if (!!getMathformulaByElement(el)) {
593
- marks = mergeObject(marks, cloneData(el.marks!))!
630
+ marks = mergeObject(marks, DapCommon.clone(el.marks!))!
594
631
  }
595
632
  //面板属性保留
596
633
  if (elementIsPanel(el)) {
@@ -621,7 +658,7 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
621
658
  }
622
659
  //数学公式内的样式全部保留
623
660
  if (!!getMathformulaByElement(el)) {
624
- styles = mergeObject(styles, cloneData(el.styles!))!
661
+ styles = mergeObject(styles, DapCommon.clone(el.styles!))!
625
662
  }
626
663
  }
627
664
  //对外的自定义属性和样式保留
@@ -635,7 +672,24 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
635
672
  el.marks = marks
636
673
  el.styles = styles
637
674
  }
675
+ //对于不在table下的这些表格元素直接置空
676
+ if (el.parsedom && ['tbody', 'tr', 'th', 'td', 'thead', 'tfooter', 'colgroup', 'col'].includes(el.parsedom)) {
677
+ const flag = !!getMatchElementByElement(el, {
678
+ parsedom: 'table'
679
+ })
680
+ if (!flag) {
681
+ el.toEmpty()
682
+ if (el.parent) {
683
+ const index = el.parent.children!.findIndex(item => item.isEqual(el))
684
+ el.parent.children!.splice(index, 1)
685
+ }
686
+ }
687
+ }
638
688
  })
689
+ elements = elements.filter(el => !el.isEmpty())
690
+ if (!elements.length) {
691
+ return
692
+ }
639
693
  //如果使用了自定义粘贴html的功能
640
694
  if (typeof props.customHtmlPaste == 'function') {
641
695
  await props.customHtmlPaste(elements)
@@ -862,27 +916,25 @@ const handleAfterRender = () => {
862
916
  //设定视频高度
863
917
  setVideoHeight()
864
918
  //附件元素下载事件设置
865
- AlexElement.flatElements(editor.value!.stack).forEach(el => {
866
- if (elementIsAttachment(el)) {
867
- DapEvent.off(el.elm as HTMLElement, 'click')
868
- //单击下载
869
- DapEvent.on(el.elm as HTMLElement, 'click', async () => {
870
- //获取文件地址
871
- const url = el.marks!['data-editify-attachment']
872
- //使用fetch读取文件地址
873
- const res = await fetch(url, {
874
- method: 'GET'
875
- })
876
- //获取blob数据
877
- const blob = await res.blob()
878
- //创建a标签进行下载
879
- const a = document.createElement('a')
880
- a.setAttribute('target', '_blank')
881
- a.setAttribute('href', URL.createObjectURL(blob))
882
- a.setAttribute('download', el.marks!['data-editify-attachment-name'])
883
- a.click()
919
+ contentRef.value!.querySelectorAll('span[data-editify-attachment]').forEach(dom => {
920
+ DapEvent.off(dom as HTMLElement, 'click')
921
+ //单击下载
922
+ DapEvent.on(dom as HTMLElement, 'click', async () => {
923
+ //获取文件地址
924
+ const url = dom.getAttribute('data-editify-attachment')!
925
+ //使用fetch读取文件地址
926
+ const res = await fetch(url, {
927
+ method: 'GET'
884
928
  })
885
- }
929
+ //获取blob数据
930
+ const blob = await res.blob()
931
+ //创建a标签进行下载
932
+ const a = document.createElement('a')
933
+ a.setAttribute('target', '_blank')
934
+ a.setAttribute('href', URL.createObjectURL(blob))
935
+ a.setAttribute('download', dom.getAttribute('data-editify-attachment-name')!)
936
+ a.click()
937
+ })
886
938
  })
887
939
  emits('updateview')
888
940
  }
@@ -12,7 +12,7 @@ export type EditifyResizeParamsType = {
12
12
  export type EditifyToolbarOptionsType = {
13
13
  show: boolean
14
14
  node: string | null
15
- type: 'text' | 'link' | 'image' | 'video' | 'table' | 'codeBlock'
15
+ type: 'text' | 'link' | 'image' | 'video' | 'table' | 'codeBlock' | 'orderList' | 'unorderList'
16
16
  }
17
17
 
18
18
  export const EditifyProps = {
@@ -19,10 +19,10 @@ export const ToolbarProps = {
19
19
  },
20
20
  //类型
21
21
  type: {
22
- type: String as PropType<'text' | 'table' | 'link' | 'codeBlock' | 'image' | 'video'>,
22
+ type: String as PropType<'text' | 'table' | 'link' | 'codeBlock' | 'image' | 'video' | 'orderList' | 'unorderList'>,
23
23
  default: 'text',
24
24
  validator(value: any) {
25
- return ['text', 'table', 'link', 'codeBlock', 'image', 'video'].includes(value)
25
+ return ['text', 'table', 'link', 'codeBlock', 'image', 'video', 'orderList', 'unorderList'].includes(value)
26
26
  }
27
27
  },
28
28
  //工具条配置