vue-editify 0.1.40 → 0.1.41

Sign up to get free protection for your applications and to get access to all the features.
package/src/core/rule.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { AlexEditor, AlexElement } from 'alex-editor'
2
2
  import { LanguagesItemType, getHljsHtml } from '../hljs'
3
- import { getColNumbers } from './tool'
4
3
  import { isList, isTask } from './function'
5
4
  import { common as DapCommon } from 'dap-util'
6
5
 
@@ -192,25 +191,55 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
192
191
  element.styles = styles
193
192
  }
194
193
  const elements = AlexElement.flatElements(element.children!)
194
+ //所有的行元素
195
195
  const rows = elements.filter(el => {
196
196
  return el.parsedom == 'tr'
197
197
  })
198
+ //colgroup元素
198
199
  let colgroup = elements.find(el => {
199
200
  return el.parsedom == 'colgroup'
200
201
  })
202
+ //理论上的col的数量:取最多列数
203
+ const colNumber = Math.max(
204
+ ...rows.map(row => {
205
+ return row.children!.length
206
+ })
207
+ )
208
+ //如果colgroup元素存在
201
209
  if (colgroup) {
210
+ //遍历每个col元素设置默认的width:'auto
202
211
  colgroup.children!.forEach(col => {
212
+ //如果没有任何标记
203
213
  if (!col.hasMarks()) {
204
214
  col.marks = {
205
215
  width: 'auto'
206
216
  }
207
- } else if (!col.marks!['width']) {
217
+ }
218
+ //如果没有width标记
219
+ else if (!col.marks!['width']) {
208
220
  col.marks!['width'] = 'auto'
209
221
  }
210
222
  })
211
- } else {
223
+ //对缺少的col元素进行补全
224
+ const length = colgroup.children!.length
225
+ if (length < colNumber) {
226
+ for (let i = 0; i < colNumber - length; i++) {
227
+ const col = new AlexElement(
228
+ 'closed',
229
+ 'col',
230
+ {
231
+ width: 'auto'
232
+ },
233
+ null,
234
+ null
235
+ )
236
+ editor.addElementTo(col, colgroup, colgroup.children!.length)
237
+ }
238
+ }
239
+ }
240
+ //如果colgroup元素不存在则新建
241
+ else {
212
242
  colgroup = new AlexElement('inblock', 'colgroup', null, null, null)
213
- const colNumber = getColNumbers(rows[0])
214
243
  for (let i = colNumber - 1; i >= 0; i--) {
215
244
  const col = new AlexElement(
216
245
  'closed',
@@ -227,6 +256,16 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
227
256
  element.children = []
228
257
  const tbody = new AlexElement('inblock', 'tbody', null, null, null)
229
258
  rows.reverse().forEach(row => {
259
+ //对缺少的列进行补全
260
+ const length = row.children!.length
261
+ if (length < colNumber) {
262
+ for (let i = 0; i < colNumber - length; i++) {
263
+ const column = new AlexElement('inblock', 'td', null, null, null)
264
+ const breakElement = new AlexElement('closed', 'br', null, null, null)
265
+ editor.addElementTo(breakElement, column)
266
+ editor.addElementTo(column, row, row.children!.length)
267
+ }
268
+ }
230
269
  editor.addElementTo(row, tbody)
231
270
  })
232
271
  editor.addElementTo(tbody, element)
@@ -235,6 +274,23 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
235
274
  if (element.parsedom == 'th') {
236
275
  element.parsedom = 'td'
237
276
  }
277
+ if (element.parsedom == 'td') {
278
+ //移除列的rowspan和colspan属性
279
+ if (element.hasMarks()) {
280
+ if (element.marks!['rowspan']) {
281
+ delete element.marks!['rowspan']
282
+ }
283
+ if (element.marks!['colspan']) {
284
+ delete element.marks!['colspan']
285
+ }
286
+ }
287
+ //移除列的display样式
288
+ if (element.hasStyles()) {
289
+ if (element.styles!['display']) {
290
+ delete element.styles!['display']
291
+ }
292
+ }
293
+ }
238
294
  }
239
295
 
240
296
  /**
package/src/core/tool.ts CHANGED
@@ -300,27 +300,6 @@ export const cloneData = function (data: any) {
300
300
  return data
301
301
  }
302
302
 
303
- /**
304
- * 根据行元素获取colgroup的col数量
305
- * @param row
306
- * @returns
307
- */
308
- export const getColNumbers = function (row: AlexElement) {
309
- const children = row.children || []
310
- let num = 0
311
- children.forEach(td => {
312
- if (td.hasMarks() && td.marks!.hasOwnProperty('colspan')) {
313
- const span = Number(td.marks!.colspan)
314
- if (!isNaN(span)) {
315
- num += span
316
- }
317
- } else {
318
- num += 1
319
- }
320
- })
321
- return num
322
- }
323
-
324
303
  /**
325
304
  * 获取菜单按钮列表数据配置
326
305
  * @param editTrans
@@ -766,7 +745,7 @@ export const getToolbarConfig = function (editTrans: (key: string) => any, editL
766
745
  rightBorder: false
767
746
  }
768
747
  },
769
- //(只对文本工具条中的按钮生效)添加额外的按钮禁用判定,回调参数为name,this指向组件实例
748
+ //(只对文本工具条中的按钮生效)添加额外的按钮禁用判定,回调参数为name
770
749
  extraDisabled: null
771
750
  }
772
751
  }
@@ -785,7 +764,7 @@ export const getMenuConfig = function (editTrans: (key: string) => any, editLoca
785
764
  tooltip: true,
786
765
  //菜单栏显示模式,支持default/inner/fixed
787
766
  mode: 'default',
788
- //添加额外的按钮禁用判定,回调参数为name,this指向组件实例
767
+ //添加额外的按钮禁用判定,回调参数为name
789
768
  extraDisabled: null,
790
769
  //菜单栏的样式自定义
791
770
  style: null,
@@ -357,7 +357,7 @@
357
357
  color: @font-color-link;
358
358
  transition: all 200ms;
359
359
  position: relative;
360
- padding: 0 10px;
360
+ margin: 0 10px;
361
361
  font-size: 14px;
362
362
  vertical-align: baseline;
363
363
 
@@ -388,6 +388,13 @@
388
388
  border-radius: 4px;
389
389
  margin: 0 4px;
390
390
  transition: all 200ms;
391
+ max-width: 100%;
392
+
393
+ .katex,
394
+ math {
395
+ width: 100%;
396
+ overflow: hidden;
397
+ }
391
398
 
392
399
  &:hover {
393
400
  cursor: pointer;
@@ -24,7 +24,7 @@ import { AlexEditor, AlexElement, AlexElementRangeType, AlexElementsRangeType }
24
24
  import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor } from 'dap-util'
25
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
- import { isTask, elementToParagraph, getCurrentParsedomElement, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange } from '../core/function'
27
+ import { isTask, elementToParagraph, getMatchElementsByRange, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange } from '../core/function'
28
28
  import Toolbar from '../components/toolbar/toolbar.vue'
29
29
  import Menu from '../components/menu/menu.vue'
30
30
  import Layer from '../components/layer/layer.vue'
@@ -180,59 +180,70 @@ const handleToolbar = () => {
180
180
  }
181
181
  hideToolbar()
182
182
  nextTick(() => {
183
- const table = getCurrentParsedomElement(editor.value!, dataRangeCaches.value, 'table')
184
- const pre = getCurrentParsedomElement(editor.value!, dataRangeCaches.value, 'pre')
185
- const link = getCurrentParsedomElement(editor.value!, dataRangeCaches.value, 'a')
186
- const image = getCurrentParsedomElement(editor.value!, dataRangeCaches.value, 'img')
187
- const video = getCurrentParsedomElement(editor.value!, dataRangeCaches.value, 'video')
188
- if (link) {
183
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
184
+ const pres = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'pre' })
185
+ const links = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'a' })
186
+ const images = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'img' })
187
+ const videos = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'video' })
188
+ //显示链接工具条
189
+ if (links.length == 1) {
189
190
  toolbarOptions.value.type = 'link'
190
- toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${link.key}"]`
191
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${links[0].key}"]`
191
192
  if (toolbarOptions.value.show) {
192
193
  ;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
193
194
  } else {
194
195
  toolbarOptions.value.show = true
195
196
  }
196
- } else if (image) {
197
+ }
198
+ //显示图片工具条
199
+ else if (images.length == 1) {
197
200
  toolbarOptions.value.type = 'image'
198
- toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${image.key}"]`
201
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${images[0].key}"]`
199
202
  if (toolbarOptions.value.show) {
200
203
  ;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
201
204
  } else {
202
205
  toolbarOptions.value.show = true
203
206
  }
204
- } else if (video) {
207
+ }
208
+ //显示视频工具条
209
+ else if (videos.length == 1) {
205
210
  toolbarOptions.value.type = 'video'
206
- toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${video.key}"]`
211
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${videos[0].key}"]`
207
212
  if (toolbarOptions.value.show) {
208
213
  ;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
209
214
  } else {
210
215
  toolbarOptions.value.show = true
211
216
  }
212
- } else if (table) {
217
+ }
218
+ //显示表格工具条
219
+ else if (tables.length == 1) {
213
220
  toolbarOptions.value.type = 'table'
214
- toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${table.key}"]`
221
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${tables[0].key}"]`
215
222
  if (toolbarOptions.value.show) {
216
223
  ;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
217
224
  } else {
218
225
  toolbarOptions.value.show = true
219
226
  }
220
- } else if (pre) {
227
+ }
228
+ //显示代码块工具条
229
+ else if (pres.length == 1) {
221
230
  toolbarOptions.value.type = 'codeBlock'
222
- toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${pre.key}"]`
231
+ toolbarOptions.value.node = `[data-editify-uid="${instance.uid}"] [data-editify-element="${pres[0].key}"]`
223
232
  if (toolbarOptions.value.show) {
224
233
  ;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
225
234
  } else {
226
235
  toolbarOptions.value.show = true
227
236
  }
228
- } else {
237
+ }
238
+ //显示文本工具条
239
+ else {
229
240
  const result = dataRangeCaches.value.flatList.filter((item: AlexElementRangeType) => {
230
241
  return item.element.isText()
231
242
  })
232
243
  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)) {
233
244
  toolbarOptions.value.type = 'text'
234
245
  if (toolbarOptions.value.show) {
235
- ;(<InstanceType<typeof Layer>>toolbarRef.value!.$refs.layerRef).setPosition()
246
+ ;(toolbarRef.value!.$refs.layerRef as InstanceType<typeof Layer>).setPosition()
236
247
  } else {
237
248
  toolbarOptions.value.show = true
238
249
  }
@@ -366,11 +377,11 @@ const documentMouseMove = (e: Event) => {
366
377
  if (!tableColumnResizeParams.value.element) {
367
378
  return
368
379
  }
369
- const table = getCurrentParsedomElement(editor.value!, dataRangeCaches.value, 'table')
370
- if (!table) {
380
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
381
+ if (tables.length != 1) {
371
382
  return
372
383
  }
373
- const colgroup = table.children!.find(item => {
384
+ const colgroup = tables[0].children!.find(item => {
374
385
  return item.parsedom == 'colgroup'
375
386
  })!
376
387
  const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
@@ -389,11 +400,11 @@ const documentMouseUp = () => {
389
400
  if (!tableColumnResizeParams.value.element) {
390
401
  return
391
402
  }
392
- const table = getCurrentParsedomElement(editor.value!, dataRangeCaches.value, 'table')
393
- if (!table) {
403
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
404
+ if (tables.length != 1) {
394
405
  return
395
406
  }
396
- const colgroup = table.children!.find(item => {
407
+ const colgroup = tables[0].children!.find(item => {
397
408
  return item.parsedom == 'colgroup'
398
409
  })!
399
410
  const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
@@ -466,10 +477,6 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
466
477
  if (el.marks!['disabled']) {
467
478
  marks['disabled'] = el.marks!['disabled']
468
479
  }
469
- //td的colspan属性保留
470
- if (el.parsedom == 'td' && el.marks!['colspan']) {
471
- marks['colspan'] = el.marks!['colspan']
472
- }
473
480
  //图片和视频的src属性保留
474
481
  if (['img', 'video'].includes(el.parsedom!) && el.marks!['src']) {
475
482
  marks['src'] = el.marks!['src']
@@ -543,12 +550,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
543
550
  })
544
551
  //对外的自定义属性和样式保留
545
552
  if (typeof props.pasteKeepMarks == 'function') {
546
- const keepMarks = props.pasteKeepMarks(el)
547
- marks = mergeObject(marks, keepMarks)!
553
+ marks = mergeObject(marks, props.pasteKeepMarks(el))!
548
554
  }
549
555
  if (typeof props.pasteKeepStyles == 'function') {
550
- const keepStyles = props.pasteKeepStyles(el)
551
- styles = mergeObject(styles, keepStyles)!
556
+ styles = mergeObject(styles, props.pasteKeepStyles(el))!
552
557
  }
553
558
  //将处理后的样式和标记给元素
554
559
  el.marks = marks
Binary file
Binary file
package/src/index.ts CHANGED
@@ -9,16 +9,17 @@ export type { ButtonTypeType, ButtonOptionsItemType, ButtonSelectConfigType, But
9
9
  export type { InsertImageUploadErrorType } from './components/insertImage/props'
10
10
  export type { InsertVideoUploadErrorType } from './components/insertVideo/props'
11
11
  export type { MenuButtonType, MenuSelectButtonType, MenuDisplayButtonType, MenuImageButtonType, MenuVideoButtonType, MenuTableButtonType, MenuCustomButtonType, CodeBlockToolbarType, TextToolbarType, ToolbarConfigType, MenuSequenceType, MenuModeType, MenuExtendType, MenuConfigType, PluginType, PluginResultType } from './core/tool'
12
+ export type { ElementMatchConfig } from './core/function'
12
13
 
13
14
  //导出编辑器操作方法
14
- export { getParsedomElementByElement, getCurrentParsedomElement, elementIsInList, elementIsInTask, isList, isTask, hasPreInRange, isRangeInPre, hasQuoteInRange, isRangeInQuote, hasListInRange, isRangeInList, hasTaskInRange, isRangeInTask, hasLinkInRange, hasTableInRange, hasImageInRange, hasVideoInRange, queryTextStyle, queryTextMark, getRangeText, setIndentIncrease, setIndentDecrease, setQuote, setAlign, setList, setTask, setTextStyle, setTextMark, removeTextStyle, removeTextMark, setLineHeight, insertLink, insertImage, insertVideo, insertTable, insertCodeBlock } from './core/function'
15
+ export { elementIsMatch, getMatchElementByElement, getMatchElementsByRange, elementIsInList, elementIsInTask, isList, isTask, hasPreInRange, isRangeInPre, hasQuoteInRange, isRangeInQuote, hasListInRange, isRangeInList, hasTaskInRange, isRangeInTask, hasLinkInRange, hasTableInRange, hasImageInRange, hasVideoInRange, queryTextStyle, queryTextMark, getRangeText, setIndentIncrease, setIndentDecrease, setQuote, setAlign, setList, setTask, setTextStyle, setTextMark, removeTextStyle, removeTextMark, setLineHeight, insertLink, insertImage, insertVideo, insertTable, insertCodeBlock } from './core/function'
15
16
 
16
17
  //安装函数
17
18
  const install: FunctionPlugin = (app: App) => {
18
19
  app.component(Editify.name!, Editify)
19
20
  }
20
21
  //版本号
21
- const version = '0.1.40'
22
+ const version = '0.1.41'
22
23
 
23
24
  //导出AlexElement元素
24
25
  export { AlexElement } from 'alex-editor'
@@ -99,5 +99,6 @@ export const en_US: ObjectType = {
99
99
 
100
100
  //数学公式插件语言配置
101
101
  insertMathformula: 'Insert mathematical formula',
102
+ editMathformula: 'Edit mathematical formula',
102
103
  mathformulaPlaceholder: 'Please enter LaTex syntax'
103
104
  }
@@ -99,5 +99,6 @@ export const zh_CN: ObjectType = {
99
99
 
100
100
  //数学公式插件语言配置
101
101
  insertMathformula: '插入数学公式',
102
+ editMathformula: '编辑数学公式',
102
103
  mathformulaPlaceholder: '请输入LaTex语法'
103
104
  }
@@ -1,7 +1,6 @@
1
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
-
5
4
  import { AlexEditor, AlexElement, AlexElementsRangeType } from 'alex-editor'
6
5
  import 'katex/dist/katex.css'
7
6
  import KaTex from 'katex'
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="editify-mathformula">
3
- <div class="editify-mathformula-label">{{ $editTrans('insertMathformula') }}</div>
3
+ <div class="editify-mathformula-label">{{ props.defaultLaTexContent ? $editTrans('editMathformula') : $editTrans('insertMathformula') }}</div>
4
4
  <textarea class="editify-mathformula-textarea" v-model.trim="latexContent" :placeholder="$editTrans('mathformulaPlaceholder')" @focus="handleInputFocus" @blur="handleInputBlur"></textarea>
5
5
  <div class="editify-mathformula-footer">
6
6
  <span :style="{ color: color || '' }" @click="insertMathformula">{{ $editTrans('confirm') }}</span>