vue-editify 0.1.39 → 0.1.40

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-editify",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -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
 
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.39'
21
+ const version = '0.1.40'
22
22
 
23
23
  //导出AlexElement元素
24
24
  export { AlexElement } from 'alex-editor'
@@ -29,7 +29,7 @@ export type { InsertAttachmentUploadErrorType } from './plugins/attachment/inser
29
29
  export { attachment, isAttachment, hasAttachmentInRange } from './plugins/attachment'
30
30
  //导出mathformula插件相关的方法和类型
31
31
  export type { MathformulaOptionsType } from './plugins/mathformula'
32
- export { mathformula, isMathformula, isUnderMathformula, getMathformulaElement } from './plugins/mathformula'
32
+ export { mathformula, isMathformula, isUnderMathformula, getMathformulaElement, hasMathformulaInRange, getMathformulaElementByRange } from './plugins/mathformula'
33
33
 
34
34
  //导出组件和安装函数
35
35
  export { install as default, install, Editify, version }
@@ -1,4 +1,4 @@
1
- import { common as DapCommon, element as DapElement } from 'dap-util'
1
+ import { common as DapCommon } from 'dap-util'
2
2
  import { ObjectType, PluginType, cloneData } from '../../core/tool'
3
3
  import { ComponentInternalInstance, h } from 'vue'
4
4
 
@@ -21,6 +21,8 @@ export type MathformulaOptionsType = {
21
21
  rightBorder?: boolean
22
22
  //按钮是否禁用
23
23
  disabled?: boolean
24
+ //公式异常处理
25
+ handleError?: (error: Error) => void
24
26
  }
25
27
 
26
28
  /**
@@ -32,7 +34,11 @@ export const isMathformula = (el: AlexElement) => {
32
34
  return el.parsedom == 'span' && el.hasMarks() && el.marks!['data-editify-mathformula']
33
35
  }
34
36
 
35
- //是否在公式元素下
37
+ /**
38
+ * 判断某个元素是否在公式元素内
39
+ * @param el
40
+ * @returns
41
+ */
36
42
  export const isUnderMathformula = (el: AlexElement): boolean => {
37
43
  if (isMathformula(el)) {
38
44
  return true
@@ -43,7 +49,11 @@ export const isUnderMathformula = (el: AlexElement): boolean => {
43
49
  return false
44
50
  }
45
51
 
46
- //获取公式元素
52
+ /**
53
+ * 根据某个元素获取所在的公式元素,如果不在公式元素内则返回null
54
+ * @param el
55
+ * @returns
56
+ */
47
57
  export const getMathformulaElement = (el: AlexElement): AlexElement | null => {
48
58
  if (isMathformula(el)) {
49
59
  return el
@@ -72,6 +82,48 @@ export const hasMathformulaInRange = (editor: AlexEditor, dataRangeCaches: AlexE
72
82
  })
73
83
  }
74
84
 
85
+ /**
86
+ * 选区是否在某个公式元素下,如果是返回该公式元素否则返回null
87
+ * @param editor
88
+ * @param dataRangeCaches
89
+ * @returns
90
+ */
91
+ export const getMathformulaElementByRange = (editor: AlexEditor, dataRangeCaches: AlexElementsRangeType) => {
92
+ if (!editor.range) {
93
+ return null
94
+ }
95
+ if (editor.range.anchor.element.isEqual(editor.range.focus.element)) {
96
+ return getMathformulaElement(editor.range.anchor.element)
97
+ }
98
+ const arr = dataRangeCaches.list.map(item => {
99
+ return getMathformulaElement(item.element)
100
+ })
101
+ let hasNull = arr.some(el => {
102
+ return el == null
103
+ })
104
+ //如果存在null,则表示有的选区元素不在公式元素下,返回null
105
+ if (hasNull) {
106
+ return null
107
+ }
108
+ //如果只有一个元素,则返回该元素
109
+ if (arr.length == 1) {
110
+ return arr[0]!
111
+ }
112
+ //默认数组中的元素都相等
113
+ let flag = true
114
+ for (let i = 1; i < arr.length; i++) {
115
+ if (!arr[i]!.isEqual(arr[0]!)) {
116
+ flag = false
117
+ break
118
+ }
119
+ }
120
+ //如果相等,则返回该元素
121
+ if (flag) {
122
+ return arr[0]
123
+ }
124
+ return null
125
+ }
126
+
75
127
  /**
76
128
  * 数学公式插件
77
129
  * @param options
@@ -82,18 +134,23 @@ export const mathformula = (options?: MathformulaOptionsType) => {
82
134
  options = {}
83
135
  }
84
136
  const plugin: PluginType = (editifyInstance: ComponentInternalInstance, editTrans: (key: string) => any) => {
85
- let isDisabled = false
86
- //如果光标范围内有数学公式、链接、代码块则禁用
137
+ //是否禁用该插件按钮
138
+ let isDisabled: boolean = false
139
+ //如果光标范围内有链接、代码块则禁用
87
140
  if (editifyInstance.exposed!.editor.value) {
88
- 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)
141
+ isDisabled = hasPreInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) || hasLinkInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
89
142
  }
143
+ //数学公式文本框内置LaTex文本内容
144
+ let defaultLaTexContent: string = ''
145
+
90
146
  return {
147
+ //插件名称
91
148
  name: 'mathformula',
92
149
  //菜单项配置
93
150
  menu: {
94
151
  sequence: options!.sequence || 101,
95
152
  extraDisabled: (name: string) => {
96
- //如果光标选区内有数学公式则禁用链接菜单、代码块菜单
153
+ //如果光标选区内有数学公式则禁用链接、图片、视频、表格和代码块菜单
97
154
  if (name == 'link' || name == 'image' || name == 'video' || name == 'table' || name == 'codeBlock') {
98
155
  return hasMathformulaInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
99
156
  }
@@ -105,36 +162,67 @@ export const mathformula = (options?: MathformulaOptionsType) => {
105
162
  leftBorder: options!.leftBorder,
106
163
  rightBorder: options!.rightBorder,
107
164
  hideScroll: true,
108
- active: false,
165
+ active: editifyInstance.exposed!.editor.value ? hasMathformulaInRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value) : false,
109
166
  disabled: isDisabled || options!.disabled,
167
+ //浮层展开时触发的事件
168
+ onLayerShow() {
169
+ //获取选区所在的数学公式元素
170
+ const mathformulaElement = getMathformulaElementByRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
171
+ //如果该元素存在,则设置默认的LaTex文本内容
172
+ if (mathformulaElement) {
173
+ defaultLaTexContent = mathformulaElement.marks!['data-editify-mathformula'] || ''
174
+ }
175
+ },
110
176
  default: () => h(Icon, { value: 'mathformula' }),
111
177
  layer: (_name: string, btnInstance: InstanceType<typeof Button>) => {
112
178
  return h(InsertMathformula, {
113
179
  color: <string | null>editifyInstance.props.color,
180
+ defaultLaTexContent: defaultLaTexContent,
114
181
  onInsert: (content: string) => {
182
+ //如果公式文本框有内容则进行下一步处理
115
183
  if (content) {
116
184
  //获取编辑器对象
117
185
  const editor = <AlexEditor>editifyInstance.exposed!.editor.value
118
- //渲染LaTex为mathml并转为dom
119
- const dom = DapElement.string2dom(
120
- KaTex.renderToString(content, {
186
+ //获取选区所在的数学公式元素
187
+ const mathformulaElement = getMathformulaElementByRange(editifyInstance.exposed!.editor.value, editifyInstance.exposed!.dataRangeCaches.value)
188
+ //如果在数学公式下
189
+ if (mathformulaElement) {
190
+ //清除该数学公式
191
+ mathformulaElement.toEmpty()
192
+ //移动光标到后一个元素上
193
+ editor.range!.anchor.moveToStart(editor.getNextElement(mathformulaElement)!)
194
+ editor.range!.focus.moveToStart(editor.getNextElement(mathformulaElement)!)
195
+ }
196
+ //定义转换后的mathml内容
197
+ let mathml: string = ''
198
+ try {
199
+ //获取转换后的mathml
200
+ mathml = KaTex.renderToString(content, {
121
201
  output: 'mathml',
122
- throwOnError: false
202
+ throwOnError: true
123
203
  })
124
- ) as HTMLElement
125
- //设置最终的html内容
126
- const html = `<span data-editify-mathformula="true" class="katex" >${dom.innerHTML}</span>`
127
- //html内容转为元素数组
128
- const elements = editor.parseHtml(html)
129
- //插入编辑器
130
- editor.insertElement(elements[0])
131
- //移动光标到新插入的元素
132
- editor.range!.anchor.moveToEnd(elements[0])
133
- editor.range!.focus.moveToEnd(elements[0])
134
- //渲染
135
- editor.formatElementStack()
136
- editor.domRender()
137
- editor.rangeRender()
204
+ } catch (error) {
205
+ mathml = ''
206
+ if (typeof options!.handleError == 'function') {
207
+ options!.handleError(error as Error)
208
+ }
209
+ }
210
+ //如果mathml存在则表示数学公式渲染成功则插入到编辑器
211
+ if (mathml) {
212
+ //设置最终的html内容
213
+ const html = `<span data-editify-mathformula="${content}" contenteditable="false">${mathml}</span>`
214
+ //html内容转为元素数组
215
+ const elements = editor.parseHtml(html)
216
+ //插入编辑器
217
+ editor.insertElement(elements[0])
218
+ //移动光标到新插入的元素
219
+ editor.range!.anchor.moveToEnd(elements[0])
220
+ editor.range!.focus.moveToEnd(elements[0])
221
+ //渲染
222
+ editor.formatElementStack()
223
+ editor.domRender()
224
+ editor.rangeRender()
225
+ }
138
226
  }
139
227
  //关闭浮层
140
228
  btnInstance.show = false
@@ -8,7 +8,7 @@
8
8
  </div>
9
9
  </template>
10
10
  <script setup lang="ts">
11
- import { inject, ref } from 'vue'
11
+ import { inject, ref, watch } from 'vue'
12
12
  import { InsertMathformulaProps } from './props'
13
13
 
14
14
  defineOptions({
@@ -36,5 +36,15 @@ const handleInputBlur = (e: Event) => {
36
36
  const insertMathformula = () => {
37
37
  emits('insert', latexContent.value)
38
38
  }
39
+
40
+ watch(
41
+ () => props.defaultLaTexContent,
42
+ newVal => {
43
+ latexContent.value = newVal
44
+ },
45
+ {
46
+ immediate: true
47
+ }
48
+ )
39
49
  </script>
40
50
  <style scoped src="./insertMathformula.less"></style>
@@ -5,6 +5,11 @@ export const InsertMathformulaProps = {
5
5
  color: {
6
6
  type: String as PropType<string | null>,
7
7
  default: ''
8
+ },
9
+ //预置的LaTex文本内容
10
+ defaultLaTexContent: {
11
+ type: String,
12
+ default: ''
8
13
  }
9
14
  }
10
15