vue-editify 0.1.39 → 0.1.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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