vue-editify 0.1.37 → 0.1.40

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. package/examples/App.vue +6 -10
  2. package/lib/components/button/button.vue.d.ts +13 -13
  3. package/lib/components/button/props.d.ts +1 -1
  4. package/lib/components/checkbox/checkbox.vue.d.ts +10 -10
  5. package/lib/components/checkbox/props.d.ts +1 -1
  6. package/lib/components/colors/colors.vue.d.ts +6 -6
  7. package/lib/components/colors/props.d.ts +1 -1
  8. package/lib/components/icon/icon.vue.d.ts +1 -1
  9. package/lib/components/insertImage/insertImage.vue.d.ts +11 -11
  10. package/lib/components/insertLink/insertLink.vue.d.ts +4 -4
  11. package/lib/components/insertTable/insertTable.vue.d.ts +4 -4
  12. package/lib/components/insertVideo/insertVideo.vue.d.ts +11 -11
  13. package/lib/components/layer/layer.vue.d.ts +9 -9
  14. package/lib/components/menu/menu.vue.d.ts +6 -6
  15. package/lib/components/menu/props.d.ts +1 -1
  16. package/lib/components/toolbar/props.d.ts +1 -1
  17. package/lib/components/toolbar/toolbar.vue.d.ts +11 -11
  18. package/lib/components/tooltip/tooltip.vue.d.ts +1 -1
  19. package/lib/components/triangle/triangle.vue.d.ts +4 -4
  20. package/lib/core/function.d.ts +1 -1
  21. package/lib/core/rule.d.ts +1 -1
  22. package/lib/core/tool.d.ts +8 -11
  23. package/lib/editify/editify.vue.d.ts +110 -84
  24. package/lib/editify/props.d.ts +9 -5
  25. package/lib/editify.es.js +15225 -404
  26. package/lib/editify.umd.js +1 -1
  27. package/lib/index.d.ts +4 -2
  28. package/lib/plugins/attachment/index.d.ts +3 -2
  29. package/lib/plugins/attachment/insertAttachment/insertAttachment.vue.d.ts +11 -11
  30. package/lib/plugins/mathformula/index.d.ts +49 -0
  31. package/lib/plugins/mathformula/insertMathformula/insertMathformula.vue.d.ts +27 -0
  32. package/lib/plugins/mathformula/insertMathformula/props.d.ts +13 -0
  33. package/lib/style.css +1 -1
  34. package/package.json +4 -2
  35. package/src/components/insertImage/insertImage.less +1 -0
  36. package/src/components/insertLink/insertLink.less +1 -0
  37. package/src/components/insertVideo/insertVideo.less +1 -0
  38. package/src/core/function.ts +4 -12
  39. package/src/core/rule.ts +7 -0
  40. package/src/core/tool.ts +3 -33
  41. package/src/editify/editify.less +28 -3
  42. package/src/editify/editify.vue +111 -26
  43. package/src/editify/props.ts +11 -4
  44. package/src/icon/iconfont.css +4 -0
  45. package/src/icon/iconfont.ttf +0 -0
  46. package/src/icon/iconfont.woff +0 -0
  47. package/src/index.ts +4 -1
  48. package/src/locale/en_US.ts +6 -1
  49. package/src/locale/zh_CN.ts +7 -2
  50. package/src/plugins/attachment/index.ts +26 -15
  51. package/src/plugins/attachment/insertAttachment/insertAttachment.less +1 -0
  52. package/src/plugins/mathformula/index.ts +298 -0
  53. package/src/plugins/mathformula/insertMathformula/insertMathformula.less +64 -0
  54. package/src/plugins/mathformula/insertMathformula/insertMathformula.vue +50 -0
  55. package/src/plugins/mathformula/insertMathformula/props.ts +16 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-editify",
3
- "version": "0.1.37",
3
+ "version": "0.1.40",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -17,12 +17,14 @@
17
17
  "lib": "vue-tsc && vite build"
18
18
  },
19
19
  "dependencies": {
20
- "alex-editor": "^1.3.37",
20
+ "alex-editor": "^1.4.6",
21
21
  "dap-util": "^1.5.4",
22
22
  "highlight.js": "^11.8.0",
23
+ "katex": "^0.16.10",
23
24
  "vue": "^3.4.19"
24
25
  },
25
26
  "devDependencies": {
27
+ "@types/katex": "^0.16.7",
26
28
  "@types/node": "^20.11.24",
27
29
  "@vitejs/plugin-vue": "^5.0.4",
28
30
  "less": "^3.0.4",
@@ -80,6 +80,7 @@
80
80
  background-color: transparent;
81
81
  outline: none;
82
82
  box-sizing: border-box;
83
+ font-family: inherit;
83
84
 
84
85
  &::-webkit-input-placeholder,
85
86
  &::placeholder {
@@ -28,6 +28,7 @@
28
28
  background-color: transparent;
29
29
  outline: none;
30
30
  box-sizing: border-box;
31
+ font-family: inherit;
31
32
 
32
33
  &::-webkit-input-placeholder,
33
34
  &::placeholder {
@@ -80,6 +80,7 @@
80
80
  background-color: transparent;
81
81
  outline: none;
82
82
  box-sizing: border-box;
83
+ font-family: inherit;
83
84
 
84
85
  &::-webkit-input-placeholder,
85
86
  &::placeholder {
@@ -1250,12 +1250,8 @@ export const insertVideo = (editor: AlexEditor, value: string) => {
1250
1250
  null
1251
1251
  )
1252
1252
  editor.insertElement(video)
1253
- const leftSpace = AlexElement.getSpaceElement()
1254
- const rightSpace = AlexElement.getSpaceElement()
1255
- editor.addElementAfter(rightSpace, video)
1256
- editor.addElementBefore(leftSpace, video)
1257
- editor.range.anchor.moveToEnd(rightSpace)
1258
- editor.range.focus.moveToEnd(rightSpace)
1253
+ editor.range.anchor.moveToEnd(video)
1254
+ editor.range.focus.moveToEnd(video)
1259
1255
  }
1260
1256
 
1261
1257
  /**
@@ -1384,10 +1380,6 @@ export const insertSeparator = (editor: AlexEditor) => {
1384
1380
  }
1385
1381
  const separator = new AlexElement('closed', 'hr', null, null, null)
1386
1382
  editor.insertElement(separator)
1387
- const leftSpace = AlexElement.getSpaceElement()
1388
- const rightSpace = AlexElement.getSpaceElement()
1389
- editor.addElementAfter(rightSpace, separator)
1390
- editor.addElementBefore(leftSpace, separator)
1391
- editor.range.anchor.moveToEnd(rightSpace)
1392
- editor.range.focus.moveToEnd(rightSpace)
1383
+ editor.range.anchor.moveToEnd(separator)
1384
+ editor.range.focus.moveToEnd(separator)
1393
1385
  }
package/src/core/rule.ts CHANGED
@@ -144,6 +144,13 @@ export const commonElementHandle = function (editor: AlexEditor, element: AlexEl
144
144
  const spaceText = AlexElement.getSpaceElement()
145
145
  editor.addElementAfter(spaceText, element)
146
146
  }
147
+ //如果光标在视频上则更新光标位置
148
+ if (editor.range && element.isContains(editor.range.anchor.element)) {
149
+ editor.range.anchor.moveToEnd(editor.getNextElement(element)!)
150
+ }
151
+ if (editor.range && element.isContains(editor.range.focus.element)) {
152
+ editor.range.focus.moveToEnd(editor.getNextElement(element)!)
153
+ }
147
154
  }
148
155
 
149
156
  //将code转为span[data-editify-code]
package/src/core/tool.ts CHANGED
@@ -210,44 +210,14 @@ export type PluginResultType = {
210
210
  menu?: PluginMenuConfigType
211
211
  updateView?: () => void
212
212
  customParseNode?: (element: AlexElement) => AlexElement
213
+ extraKeepTags?: string[]
213
214
  renderRule?: (el: AlexElement) => void
214
- pasteKeepStyles?: ObjectType
215
- pasteKeepMarks?: ObjectType
215
+ pasteKeepMarks?: (el: AlexElement) => ObjectType
216
+ pasteKeepStyles?: (el: AlexElement) => ObjectType
216
217
  }
217
218
 
218
219
  export type PluginType = (editifyInstance: ComponentInternalInstance, editTrans: (key: string) => any) => PluginResultType
219
220
 
220
- /**
221
- * 粘贴html时保留的数据
222
- */
223
- export const pasteKeepData: ObjectType = {
224
- //粘贴html时元素保留的样式(全部元素)
225
- marks: {
226
- 'data-editify-list': ['div'],
227
- 'data-editify-value': ['div'],
228
- 'data-editify-code': ['span'],
229
- 'data-editify-task': ['div'],
230
- contenteditable: '*',
231
- src: ['img', 'video'],
232
- autoplay: ['video'],
233
- loop: ['video'],
234
- muted: ['video'],
235
- href: ['a'],
236
- target: ['a'],
237
- alt: ['img'],
238
- controls: ['video'],
239
- name: '*',
240
- disabled: '*',
241
- colspan: ['td']
242
- },
243
- //粘贴html时非文本元素保留的样式
244
- styles: {
245
- 'text-indent': '*',
246
- 'text-align': '*',
247
- 'line-height': '*'
248
- }
249
- }
250
-
251
221
  /**
252
222
  * 对象平替值方法
253
223
  * @param o1
@@ -156,7 +156,7 @@
156
156
  }
157
157
  }
158
158
  //代码样式
159
- :deep(span[data-editify-code]) {
159
+ :deep([data-editify-code]) {
160
160
  display: inline-block;
161
161
  padding: 3px 6px;
162
162
  margin: 0 4px;
@@ -380,6 +380,21 @@
380
380
  }
381
381
  }
382
382
 
383
+ //数学公式样式
384
+ :deep(span[data-editify-mathformula]) {
385
+ display: inline-block;
386
+ border: 1px dashed @border-color;
387
+ padding: 6px 10px;
388
+ border-radius: 4px;
389
+ margin: 0 4px;
390
+ transition: all 200ms;
391
+
392
+ &:hover {
393
+ cursor: pointer;
394
+ background: @background-dark;
395
+ }
396
+ }
397
+
383
398
  //禁用样式
384
399
  &.editify-disabled {
385
400
  cursor: auto !important;
@@ -387,16 +402,26 @@
387
402
  &.editify-placeholder::before {
388
403
  cursor: auto;
389
404
  }
390
-
391
405
  :deep(a) {
392
406
  cursor: pointer;
393
407
  }
394
-
395
408
  :deep(table) {
396
409
  td:not(:last-child)::after {
397
410
  cursor: auto;
398
411
  }
399
412
  }
413
+ :deep(span[data-editify-mathformula]) {
414
+ display: inline-block;
415
+ border: none;
416
+ padding: 6px 10px;
417
+ border-radius: none;
418
+ margin: 0 4px;
419
+
420
+ &:hover {
421
+ cursor: auto;
422
+ background: none;
423
+ }
424
+ }
400
425
  }
401
426
  }
402
427
 
@@ -22,7 +22,7 @@
22
22
  import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
23
23
  import { AlexEditor, AlexElement, AlexElementRangeType, AlexElementsRangeType } from 'alex-editor'
24
24
  import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor } from 'dap-util'
25
- import { pasteKeepData, mergeObject, getToolbarConfig, getMenuConfig, MenuConfigType, ObjectType, ToolbarConfigType, PluginResultType } from '../core/tool'
25
+ import { mergeObject, getToolbarConfig, getMenuConfig, MenuConfigType, ObjectType, ToolbarConfigType, PluginResultType } from '../core/tool'
26
26
  import { parseList, orderdListHandle, commonElementHandle, tableHandle, preHandle, specialInblockHandle } from '../core/rule'
27
27
  import { isTask, elementToParagraph, getCurrentParsedomElement, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange } from '../core/function'
28
28
  import Toolbar from '../components/toolbar/toolbar.vue'
@@ -249,6 +249,18 @@ const createEditor = () => {
249
249
  pluginRules.push(pluginResult.renderRule)
250
250
  }
251
251
  })
252
+ //注册插件:将插件定义的额外保留的标签数组与配置合并
253
+ let extraKeepTags: string[] = [...props.extraKeepTags]
254
+ pluginResultList.value.forEach(pluginResult => {
255
+ if (pluginResult.extraKeepTags && Array.isArray(pluginResult.extraKeepTags)) {
256
+ pluginResult.extraKeepTags.forEach(tag => {
257
+ //如果不包含则加入数组
258
+ if (!extraKeepTags.includes(tag)) {
259
+ extraKeepTags.push(tag)
260
+ }
261
+ })
262
+ }
263
+ })
252
264
  //创建编辑器
253
265
  editor.value = new AlexEditor(contentRef.value!, {
254
266
  value: value.value,
@@ -285,7 +297,8 @@ const createEditor = () => {
285
297
  customFilePaste: props.customFilePaste,
286
298
  customHtmlPaste: handleCustomHtmlPaste,
287
299
  customMerge: handleCustomMerge,
288
- customParseNode: handleCustomParseNode
300
+ customParseNode: handleCustomParseNode,
301
+ extraKeepTags: extraKeepTags
289
302
  })
290
303
  //编辑器渲染后会有一个渲染过程,会改变内容,因此重新获取内容的值来设置value
291
304
  internalModify(editor.value.value)
@@ -435,39 +448,111 @@ const documentClick = (e: Event) => {
435
448
  }
436
449
  //重新定义编辑器粘贴html
437
450
  const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
438
- let keepStyles = pasteKeepData.styles
439
- let keepMarks = pasteKeepData.marks
440
- //注册插件:自定义html粘贴保留
441
- pluginResultList.value.forEach(pluginResult => {
442
- keepStyles = Object.assign(keepStyles, pluginResult.pasteKeepStyles || {})
443
- keepMarks = Object.assign(keepMarks, pluginResult.pasteKeepMarks || {})
444
- })
445
- keepStyles = Object.assign(keepStyles, props.pasteKeepStyles || {})
446
- keepMarks = Object.assign(keepMarks, props.pasteKeepMarks || {})
447
- //粘贴html时过滤元素的样式和属性
448
451
  AlexElement.flatElements(elements).forEach(el => {
449
- let marks: ObjectType = {}
450
- let styles: ObjectType = {}
451
- //非文本元素
452
452
  if (!el.isText()) {
453
- //对标记进行处理
453
+ let marks: ObjectType = {}
454
+ let styles: ObjectType = {}
455
+ //处理需要保留的标记
454
456
  if (el.hasMarks()) {
455
- for (let key in keepMarks) {
456
- if (el.marks!.hasOwnProperty(key) && ((Array.isArray(keepMarks[key]) && keepMarks[key].includes(el.parsedom)) || keepMarks[key] == '*')) {
457
- marks[key] = el.marks![key]
457
+ //contenteditable属性保留
458
+ if (el.marks!['contenteditable']) {
459
+ marks['contenteditable'] = el.marks!['contenteditable']
460
+ }
461
+ //name属性保留
462
+ if (el.marks!['name']) {
463
+ marks['name'] = el.marks!['name']
464
+ }
465
+ //disabled属性保留
466
+ if (el.marks!['disabled']) {
467
+ marks['disabled'] = el.marks!['disabled']
468
+ }
469
+ //td的colspan属性保留
470
+ if (el.parsedom == 'td' && el.marks!['colspan']) {
471
+ marks['colspan'] = el.marks!['colspan']
472
+ }
473
+ //图片和视频的src属性保留
474
+ if (['img', 'video'].includes(el.parsedom!) && el.marks!['src']) {
475
+ marks['src'] = el.marks!['src']
476
+ }
477
+ //视频的autoplay属性保留
478
+ if (el.parsedom == 'video' && el.marks!['autoplay']) {
479
+ marks['autoplay'] = el.marks!['autoplay']
480
+ }
481
+ //视频的loop属性保留
482
+ if (el.parsedom == 'video' && el.marks!['loop']) {
483
+ marks['loop'] = el.marks!['loop']
484
+ }
485
+ //视频的muted属性保留
486
+ if (el.parsedom == 'video' && el.marks!['muted']) {
487
+ marks['muted'] = el.marks!['muted']
488
+ }
489
+ //视频的controls属性保留
490
+ if (el.parsedom == 'video' && el.marks!['controls']) {
491
+ marks['controls'] = el.marks!['controls']
492
+ }
493
+ //链接的href属性保留
494
+ if (el.parsedom == 'a' && el.marks!['href']) {
495
+ marks['href'] = el.marks!['href']
496
+ }
497
+ //链接的target属性保留
498
+ if (el.parsedom == 'a' && el.marks!['target']) {
499
+ marks['target'] = el.marks!['target']
500
+ }
501
+ //有序和无序列表属性保留
502
+ if (el.parsedom == 'div' && el.marks!['data-editify-list']) {
503
+ marks['data-editify-list'] = el.marks!['data-editify-list']
504
+ //有序列表保留序列号标记
505
+ if (el.marks!['data-editify-value']) {
506
+ marks['data-editify-value'] = el.marks!['data-editify-value']
458
507
  }
459
508
  }
460
- el.marks = marks
509
+ //行内代码属性保留
510
+ if (el.parsedom == AlexElement.TEXT_NODE && el.marks!['data-editify-code']) {
511
+ marks['data-editify-code'] = el.marks!['data-editify-code']
512
+ }
513
+ //任务列表属性保留
514
+ if (el.parsedom == 'div' && el.marks!['data-editify-task']) {
515
+ marks['data-editify-task'] = el.marks!['data-editify-task']
516
+ }
461
517
  }
462
- //对样式进行处理
518
+ //处理需要保留的样式
463
519
  if (el.hasStyles()) {
464
- for (let key in keepStyles) {
465
- if (el.styles!.hasOwnProperty(key) && ((Array.isArray(keepStyles[key]) && keepStyles[key].includes(el.parsedom)) || keepStyles[key] == '*')) {
466
- styles[key] = el.styles![key]
467
- }
520
+ //块元素保留text-indent样式
521
+ if ((el.isBlock() || el.isInblock()) && el.styles!['text-indent']) {
522
+ styles['text-indent'] = el.styles!['text-indent']
468
523
  }
469
- el.styles = styles
524
+ //块元素保留text-align样式
525
+ if ((el.isBlock() || el.isInblock()) && el.styles!['text-align']) {
526
+ styles['text-align'] = el.styles!['text-align']
527
+ }
528
+ //块元素保留line-height样式
529
+ if ((el.isBlock() || el.isInblock()) && el.styles!['line-height']) {
530
+ styles['line-height'] = el.styles!['line-height']
531
+ }
532
+ }
533
+ //注册插件:自定义属性和样式的保留
534
+ pluginResultList.value.forEach(pluginResult => {
535
+ if (typeof pluginResult.pasteKeepMarks == 'function') {
536
+ const keepMarks = pluginResult.pasteKeepMarks(el)
537
+ marks = mergeObject(marks, keepMarks)!
538
+ }
539
+ if (typeof pluginResult.pasteKeepStyles == 'function') {
540
+ const keepStyles = pluginResult.pasteKeepStyles(el)
541
+ styles = mergeObject(styles, keepStyles)!
542
+ }
543
+ })
544
+ //对外的自定义属性和样式保留
545
+ if (typeof props.pasteKeepMarks == 'function') {
546
+ const keepMarks = props.pasteKeepMarks(el)
547
+ marks = mergeObject(marks, keepMarks)!
548
+ }
549
+ if (typeof props.pasteKeepStyles == 'function') {
550
+ const keepStyles = props.pasteKeepStyles(el)
551
+ styles = mergeObject(styles, keepStyles)!
470
552
  }
553
+ //将处理后的样式和标记给元素
554
+ el.marks = marks
555
+ el.styles = styles
471
556
  }
472
557
  })
473
558
  //如果使用了自定义粘贴html的功能
@@ -119,14 +119,14 @@ export const EditifyProps = {
119
119
  type: Object as PropType<MenuConfigType>,
120
120
  default: null
121
121
  },
122
- //粘贴html时额外保留的标记(全部元素生效)
122
+ //粘贴html时对非文本元素额外保留标记的自定义处理
123
123
  pasteKeepMarks: {
124
- type: Object as PropType<ObjectType>,
124
+ type: Function as PropType<(el: AlexElement) => ObjectType>,
125
125
  default: null
126
126
  },
127
- //粘贴html时额外保留的样式(仅在非文本元素生效)
127
+ //粘贴html时对非文本元素额外保留样式的自定义处理
128
128
  pasteKeepStyles: {
129
- type: Object as PropType<ObjectType>,
129
+ type: Function as PropType<(el: AlexElement) => ObjectType>,
130
130
  default: null
131
131
  },
132
132
  //自定义node转元素时的处理
@@ -134,6 +134,13 @@ export const EditifyProps = {
134
134
  type: Function as PropType<(el: AlexElement) => AlexElement>,
135
135
  default: null
136
136
  },
137
+ //node转为元素时需要额外保留的标签数组
138
+ extraKeepTags: {
139
+ type: Array as PropType<string[]>,
140
+ default: function () {
141
+ return []
142
+ }
143
+ },
137
144
  //自定义额外的渲染规范
138
145
  renderRules: {
139
146
  type: Array as PropType<((el: AlexElement) => void)[]>,
@@ -1,3 +1,7 @@
1
+ .editify-icon-mathformula:before {
2
+ content: '\e616';
3
+ }
4
+
1
5
  .editify-icon-separator:before {
2
6
  content: '\e6e5';
3
7
  }
Binary file
Binary file
package/src/index.ts CHANGED
@@ -18,7 +18,7 @@ const install: FunctionPlugin = (app: App) => {
18
18
  app.component(Editify.name!, Editify)
19
19
  }
20
20
  //版本号
21
- const version = '0.1.37'
21
+ const version = '0.1.40'
22
22
 
23
23
  //导出AlexElement元素
24
24
  export { AlexElement } from 'alex-editor'
@@ -27,6 +27,9 @@ export { AlexElement } from 'alex-editor'
27
27
  export type { AttachmentOptionsType } from './plugins/attachment'
28
28
  export type { InsertAttachmentUploadErrorType } from './plugins/attachment/insertAttachment/props'
29
29
  export { attachment, isAttachment, hasAttachmentInRange } from './plugins/attachment'
30
+ //导出mathformula插件相关的方法和类型
31
+ export type { MathformulaOptionsType } from './plugins/mathformula'
32
+ export { mathformula, isMathformula, isUnderMathformula, getMathformulaElement, hasMathformulaInRange, getMathformulaElementByRange } from './plugins/mathformula'
30
33
 
31
34
  //导出组件和安装函数
32
35
  export { install as default, install, Editify, version }
@@ -86,6 +86,7 @@ export const en_US: ObjectType = {
86
86
  defaultLineHeight: 'Default',
87
87
  auto: 'auto',
88
88
  fullScreen: 'Full screen',
89
+ confirm: 'Confirm',
89
90
 
90
91
  //插件语言配置
91
92
  insertAttachment: 'Insert attachment',
@@ -94,5 +95,9 @@ export const en_US: ObjectType = {
94
95
  attachmentNamePlaceholder: 'Please enter the attachment name',
95
96
  attachmentUrlPlaceholder: 'Please enter the attachment address',
96
97
  attachmentDownloadTitle: 'Click to download attachment',
97
- attachmentDefaultName: 'attachment'
98
+ attachmentDefaultName: 'attachment',
99
+
100
+ //数学公式插件语言配置
101
+ insertMathformula: 'Insert mathematical formula',
102
+ mathformulaPlaceholder: 'Please enter LaTex syntax'
98
103
  }
@@ -86,13 +86,18 @@ export const zh_CN: ObjectType = {
86
86
  defaultLineHeight: '默认行高',
87
87
  auto: '自适应',
88
88
  fullScreen: '全屏',
89
+ confirm: '确定',
89
90
 
90
- //插件语言配置
91
+ //附件插件语言配置
91
92
  insertAttachment: '插入附件',
92
93
  uploadAttachment: '上传附件',
93
94
  remoteAttachment: '远程地址',
94
95
  attachmentNamePlaceholder: '请输入附件名称',
95
96
  attachmentUrlPlaceholder: '请输入附件地址',
96
97
  attachmentDownloadTitle: '点击下载附件',
97
- attachmentDefaultName: '附件'
98
+ attachmentDefaultName: '附件',
99
+
100
+ //数学公式插件语言配置
101
+ insertMathformula: '插入数学公式',
102
+ mathformulaPlaceholder: '请输入LaTex语法'
98
103
  }
@@ -8,6 +8,7 @@ import InsertAttachment from './insertAttachment/insertAttachment.vue'
8
8
  import { InsertAttachmentUploadErrorType } from './insertAttachment/props'
9
9
  import { event as DapEvent, common as DapCommon } from 'dap-util'
10
10
  import { hasLinkInRange, hasPreInRange, hasQuoteInRange } from '../../core/function'
11
+ import { hasMathformulaInRange } from '../mathformula'
11
12
 
12
13
  export type AttachmentOptionsType = {
13
14
  //排序
@@ -18,6 +19,8 @@ export type AttachmentOptionsType = {
18
19
  leftBorder?: boolean
19
20
  //按钮是否显示右侧边框
20
21
  rightBorder?: boolean
22
+ //按钮是否禁用
23
+ disabled?: boolean
21
24
  //定义可选择的文件类型,默认不限制类型,设定此参数后选择文件时会自动过滤非符合的文件类型
22
25
  accept?: string
23
26
  //支持的类型数组
@@ -75,9 +78,9 @@ export const attachment = (options?: AttachmentOptionsType) => {
75
78
  }
76
79
  const plugin: PluginType = (editifyInstance: ComponentInternalInstance, editTrans: (key: string) => any) => {
77
80
  let isDisabled = false
78
- //如果光标范围内有链接、代码块和引用则禁用
81
+ //如果光标范围内有数学公式、链接、代码块和引用则禁用
79
82
  if (editifyInstance.exposed!.editor.value) {
80
- isDisabled = hasPreInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasLinkInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasQuoteInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
83
+ isDisabled = hasMathformulaInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasPreInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasLinkInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasQuoteInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
81
84
  }
82
85
  return {
83
86
  name: 'attachment',
@@ -97,7 +100,8 @@ export const attachment = (options?: AttachmentOptionsType) => {
97
100
  leftBorder: options!.leftBorder,
98
101
  rightBorder: options!.rightBorder,
99
102
  hideScroll: true,
100
- disabled: isDisabled,
103
+ active: false,
104
+ disabled: isDisabled || options!.disabled,
101
105
  default: () => h(Icon, { value: 'attachment' }),
102
106
  layer: (_name: string, btnInstance: InstanceType<typeof Button>) =>
103
107
  h(InsertAttachment, {
@@ -131,15 +135,9 @@ export const attachment = (options?: AttachmentOptionsType) => {
131
135
  const attachmentElement = new AlexElement('closed', 'span', marks, null, null)
132
136
  //插入编辑器
133
137
  editor.insertElement(attachmentElement)
134
- //创建空文本元素
135
- const leftSpace = AlexElement.getSpaceElement()
136
- const rightSpace = AlexElement.getSpaceElement()
137
- //将空白文本元素插入附件两端
138
- editor.addElementBefore(leftSpace, attachmentElement)
139
- editor.addElementAfter(rightSpace, attachmentElement)
140
138
  //移动光标到新插入的元素
141
- editor.range!.anchor.moveToEnd(rightSpace)
142
- editor.range!.focus.moveToEnd(rightSpace)
139
+ editor.range!.anchor.moveToEnd(attachmentElement)
140
+ editor.range!.focus.moveToEnd(attachmentElement)
143
141
  })
144
142
  //渲染
145
143
  editor.formatElementStack()
@@ -185,10 +183,16 @@ export const attachment = (options?: AttachmentOptionsType) => {
185
183
  }
186
184
  return el
187
185
  },
188
- //span元素粘贴保留data-editify-attachment
189
- pasteKeepMarks: {
190
- 'data-editify-attachment': ['span'],
191
- 'data-editify-attachment-name': ['span']
186
+ //附件文件自定义保留的标记
187
+ pasteKeepMarks: el => {
188
+ const marks: ObjectType = {}
189
+ if (el.parsedom == 'span' && el.hasMarks() && el.marks!['data-editify-attachment']) {
190
+ marks['data-editify-attachment'] = el.marks!['data-editify-attachment']
191
+ if (el.marks!['data-editify-attachment-name']) {
192
+ marks['data-editify-attachment-name'] = el.marks!['data-editify-attachment-name']
193
+ }
194
+ }
195
+ return marks
192
196
  },
193
197
  //自定义渲染规范
194
198
  renderRule: (el: AlexElement) => {
@@ -215,6 +219,13 @@ export const attachment = (options?: AttachmentOptionsType) => {
215
219
  const spaceText = AlexElement.getSpaceElement()
216
220
  editor.addElementAfter(spaceText, el)
217
221
  }
222
+ //如果光标在元素上则更新光标位置
223
+ if (editor.range && el.isContains(editor.range.anchor.element)) {
224
+ editor.range.anchor.moveToEnd(editor.getNextElement(el)!)
225
+ }
226
+ if (editor.range && el.isContains(editor.range.focus.element)) {
227
+ editor.range.focus.moveToEnd(editor.getNextElement(el)!)
228
+ }
218
229
  }
219
230
  }
220
231
  }
@@ -130,6 +130,7 @@
130
130
  background-color: transparent;
131
131
  outline: none;
132
132
  box-sizing: border-box;
133
+ font-family: inherit;
133
134
 
134
135
  &::-webkit-input-placeholder,
135
136
  &::placeholder {