vue-editify 0.1.43 → 0.1.44

Sign up to get free protection for your applications and to get access to all the features.
package/src/core/rule.ts CHANGED
@@ -1,8 +1,175 @@
1
1
  import { AlexEditor, AlexElement } from 'alex-editor'
2
2
  import { LanguagesItemType, getHljsHtml } from '../hljs'
3
- import { isList, isTask } from './function'
3
+ import { isList, isTask, getTableSize, getCellSpanNumber } from './function'
4
4
  import { common as DapCommon } from 'dap-util'
5
5
 
6
+ /**
7
+ * 自动补全表格行和列
8
+ * @param editor
9
+ * @param rowElements
10
+ * @param rowNumber
11
+ * @param columnNumber
12
+ */
13
+ const autocompleteTableCells = (editor: AlexEditor, rowElements: AlexElement[], rowNumber: number, columnNumber: number) => {
14
+ //遍历所有的单元格
15
+ AlexElement.flatElements(rowElements).forEach(item => {
16
+ if (item.parsedom == 'td' && item.hasMarks()) {
17
+ //删除被合并的标识
18
+ if (item.marks!['data-editify-merged']) {
19
+ delete item.marks!['data-editify-merged']
20
+ }
21
+ //获取colspan
22
+ const colspan = isNaN(Number(item.marks!['colspan'])) ? 1 : Number(item.marks!['colspan'])
23
+ //获取rowspan
24
+ const rowspan = isNaN(Number(item.marks!['rowspan'])) ? 1 : Number(item.marks!['rowspan'])
25
+ //针对colspan>1的单元格在后面补全隐藏的单元格
26
+ if (colspan > 1) {
27
+ let i = 1
28
+ //补全的数量小于需要补全的数量并且列总数量小于理论数量
29
+ while (i < colspan && item.parent!.children!.length < columnNumber) {
30
+ const column = new AlexElement(
31
+ 'inblock',
32
+ 'td',
33
+ {
34
+ 'data-editify-merged': 'true'
35
+ },
36
+ null,
37
+ null
38
+ )
39
+ const breakElement = new AlexElement('closed', 'br', null, null, null)
40
+ editor.addElementTo(breakElement, column)
41
+ editor.addElementAfter(column, item)
42
+ i++
43
+ }
44
+ }
45
+ //针对rowspan>1的单元格在后面的行中对应位置补全隐藏的单元格
46
+ if (rowspan > 1) {
47
+ let el = item
48
+ let i = 1
49
+ while (i < rowspan && editor.getNextElement(el.parent!) && editor.getNextElement(el.parent!)!.children!.length < columnNumber) {
50
+ //下一行
51
+ const nextRow = editor.getNextElement(el.parent!)!
52
+ //单元格在行中的序列
53
+ const index = el.parent!.children!.findIndex(item => item.isEqual(el))
54
+ //下一行对应的单元格
55
+ const nextCell = nextRow.children![index]
56
+ //根据当前单元格的跨列数补充符合跨列数的隐藏单元格
57
+ for (let j = 0; j < colspan; j++) {
58
+ const column = new AlexElement(
59
+ 'inblock',
60
+ 'td',
61
+ {
62
+ 'data-editify-merged': 'true'
63
+ },
64
+ null,
65
+ null
66
+ )
67
+ const breakElement = new AlexElement('closed', 'br', null, null, null)
68
+ editor.addElementTo(breakElement, column)
69
+ if (nextCell) {
70
+ editor.addElementBefore(column, nextCell)
71
+ } else {
72
+ editor.addElementTo(column, nextRow, nextRow.children!.length)
73
+ }
74
+ }
75
+ el = nextRow.children![index]
76
+ i++
77
+ }
78
+ }
79
+ }
80
+ })
81
+ //遍历每一行,如果还缺少列则在后面补全列
82
+ rowElements.forEach(rowElement => {
83
+ //遍历该行的单元格获取总列数
84
+ const number = rowElement.children!.length
85
+ if (number < columnNumber) {
86
+ for (let i = 0; i < columnNumber - number; i++) {
87
+ const column = new AlexElement('inblock', 'td', null, null, null)
88
+ const breakElement = new AlexElement('closed', 'br', null, null, null)
89
+ editor.addElementTo(breakElement, column)
90
+ editor.addElementTo(column, rowElement, rowElement.children!.length)
91
+ }
92
+ }
93
+ })
94
+ //获取总行数
95
+ const length = rowElements.length
96
+ //判断总行数是否小于实际行数则补全行
97
+ if (length < rowNumber) {
98
+ for (let i = 0; i < rowNumber - length; i++) {
99
+ const row = new AlexElement('inblock', 'tr', null, null, null)
100
+ for (let j = 0; j < columnNumber; j++) {
101
+ const column = new AlexElement('inblock', 'td', null, null, null)
102
+ const breakElement = new AlexElement('closed', 'br', null, null, null)
103
+ editor.addElementTo(breakElement, column)
104
+ editor.addElementTo(column, row)
105
+ }
106
+ rowElements.push(row)
107
+ }
108
+ }
109
+ }
110
+
111
+ /**
112
+ * 自动隐藏被合并的单元格
113
+ * @param editor
114
+ * @param rowElements
115
+ */
116
+ const autoHideMergedTableCells = (editor: AlexEditor, rowElements: AlexElement[]) => {
117
+ const cells = AlexElement.flatElements(rowElements).filter(item => item.parsedom == 'td')
118
+ cells.forEach(cell => {
119
+ if (cell.hasMarks() && !cell.marks!['data-editify-merged']) {
120
+ //获取colspan
121
+ const colspan = isNaN(Number(cell.marks!['colspan'])) ? 1 : Number(cell.marks!['colspan'])
122
+ //获取rowspan
123
+ const rowspan = isNaN(Number(cell.marks!['rowspan'])) ? 1 : Number(cell.marks!['rowspan'])
124
+ //如果是跨列单元格,隐藏该单元格同行后的colspan-1个单元格
125
+ if (colspan > 1) {
126
+ let el = cell
127
+ let i = 1
128
+ while (i < colspan) {
129
+ const nextCell = editor.getNextElement(el)!
130
+ if (nextCell) {
131
+ if (nextCell.hasMarks()) {
132
+ nextCell.marks!['data-editify-merged'] = 'true'
133
+ } else {
134
+ nextCell.marks = {
135
+ 'data-editify-merged': 'true'
136
+ }
137
+ }
138
+ el = nextCell
139
+ i++
140
+ } else {
141
+ break
142
+ }
143
+ }
144
+ }
145
+ //如果是跨行单元格,隐藏该单元格同列后的rowspan-1行单元格
146
+ if (rowspan > 1) {
147
+ const index = cell.parent!.children!.findIndex(item => item.isEqual(cell))
148
+ let el = cell
149
+ let i = 1
150
+ while (i < rowspan && el && editor.getNextElement(el.parent!)) {
151
+ const nextRow = editor.getNextElement(el.parent!)!
152
+ //根据跨行单元格占据的列数,在后的rowspan-1行中隐藏colspan个单元格
153
+ for (let j = index; j < index + colspan; j++) {
154
+ const current = nextRow.children![j]
155
+ if (current) {
156
+ if (current.hasMarks()) {
157
+ current.marks!['data-editify-merged'] = 'true'
158
+ } else {
159
+ current.marks = {
160
+ 'data-editify-merged': 'true'
161
+ }
162
+ }
163
+ }
164
+ }
165
+ el = nextRow.children![index]
166
+ i++
167
+ }
168
+ }
169
+ }
170
+ })
171
+ }
172
+
6
173
  /**
7
174
  * 更新代码块内的光标位置
8
175
  * @param editor
@@ -94,7 +261,7 @@ export const parseList = (editor: AlexEditor, element: AlexElement) => {
94
261
  * @param editor
95
262
  * @param element
96
263
  */
97
- export const orderdListHandle = function (editor: AlexEditor, element: AlexElement) {
264
+ export const orderdListHandle = (editor: AlexEditor, element: AlexElement) => {
98
265
  //有序列表的序号处理
99
266
  if (isList(element, true)) {
100
267
  //获取前一个元素
@@ -116,7 +283,7 @@ export const orderdListHandle = function (editor: AlexEditor, element: AlexEleme
116
283
  * @param editor
117
284
  * @param element
118
285
  */
119
- export const commonElementHandle = function (editor: AlexEditor, element: AlexElement) {
286
+ export const commonElementHandle = (editor: AlexEditor, element: AlexElement) => {
120
287
  //图片、视频和链接设置marks
121
288
  if (element.parsedom == 'img' || element.parsedom == 'video' || element.parsedom == 'a') {
122
289
  const marks = {
@@ -167,11 +334,22 @@ export const commonElementHandle = function (editor: AlexEditor, element: AlexEl
167
334
  }
168
335
 
169
336
  /**
170
- * 元素格式化时处理表格
337
+ * 元素格式化时处理表格:th转为td
338
+ * @param editor
339
+ * @param element
340
+ */
341
+ export const tableThTdHandle = (_editor: AlexEditor, element: AlexElement) => {
342
+ if (element.parsedom == 'th') {
343
+ element.parsedom = 'td'
344
+ }
345
+ }
346
+
347
+ /**
348
+ * 元素格式化时处理表格:格式化表格
171
349
  * @param editor
172
350
  * @param element
173
351
  */
174
- export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
352
+ export const tableFormatHandle = (editor: AlexEditor, element: AlexElement) => {
175
353
  if (element.parsedom == 'table') {
176
354
  const marks = {
177
355
  'data-editify-element': element.key
@@ -195,16 +373,12 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
195
373
  const rows = elements.filter(el => {
196
374
  return el.parsedom == 'tr'
197
375
  })
376
+ //获取表格实际应该的规格
377
+ const { rowNumber, columnNumber } = getTableSize(rows)
198
378
  //colgroup元素
199
379
  let colgroup = elements.find(el => {
200
380
  return el.parsedom == 'colgroup'
201
381
  })
202
- //理论上的col的数量:取最多列数
203
- const colNumber = Math.max(
204
- ...rows.map(row => {
205
- return row.children!.length
206
- })
207
- )
208
382
  //如果colgroup元素存在
209
383
  if (colgroup) {
210
384
  //遍历每个col元素设置默认的width:'auto
@@ -222,8 +396,8 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
222
396
  })
223
397
  //对缺少的col元素进行补全
224
398
  const length = colgroup.children!.length
225
- if (length < colNumber) {
226
- for (let i = 0; i < colNumber - length; i++) {
399
+ if (length < columnNumber) {
400
+ for (let i = 0; i < columnNumber - length; i++) {
227
401
  const col = new AlexElement(
228
402
  'closed',
229
403
  'col',
@@ -240,7 +414,7 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
240
414
  //如果colgroup元素不存在则新建
241
415
  else {
242
416
  colgroup = new AlexElement('inblock', 'colgroup', null, null, null)
243
- for (let i = colNumber - 1; i >= 0; i--) {
417
+ for (let i = columnNumber - 1; i >= 0; i--) {
244
418
  const col = new AlexElement(
245
419
  'closed',
246
420
  'col',
@@ -253,41 +427,106 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
253
427
  editor.addElementTo(col, colgroup)
254
428
  }
255
429
  }
430
+ //自动补全表格的单元格
431
+ autocompleteTableCells(editor, rows, rowNumber, columnNumber)
432
+ //清空表格
256
433
  element.children = []
434
+ //创建tbody元素
257
435
  const tbody = new AlexElement('inblock', 'tbody', null, null, null)
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
- }
269
- editor.addElementTo(row, tbody)
436
+ //将rows全部加入表格中
437
+ rows.forEach(row => {
438
+ const index = tbody.hasChildren() ? tbody.children!.length : 0
439
+ editor.addElementTo(row, tbody, index)
270
440
  })
271
441
  editor.addElementTo(tbody, element)
272
442
  editor.addElementTo(colgroup, element)
443
+ //对表格单元格合并状态进行处理
444
+ autoHideMergedTableCells(editor, rows)
273
445
  }
274
- if (element.parsedom == 'th') {
275
- element.parsedom = 'td'
276
- }
277
- if (element.parsedom == 'td') {
278
- //移除列的rowspan和colspan属性
279
- if (element.hasMarks()) {
280
- if (element.marks!['rowspan']) {
281
- delete element.marks!['rowspan']
446
+ }
447
+
448
+ /**
449
+ * 元素格式化时处理表格:处理光标在表格隐藏单元格内的情况
450
+ * @param editor
451
+ * @param element
452
+ */
453
+ export const tableRangeMergedHandle = (editor: AlexEditor, element: AlexElement) => {
454
+ //如果元素是被隐藏的单元格,并且光标在该单元格内
455
+ if (element.parsedom == 'td' && element.hasMarks() && element.marks!['data-editify-merged'] && editor.range) {
456
+ //单元格向左查找设置焦点
457
+ const queryLeftSetRange = (_element: AlexElement, callback: (ele: AlexElement) => void) => {
458
+ //是否已查找到
459
+ let success = false
460
+ //获取前一个单元格
461
+ let el = editor.getPreviousElement(_element)
462
+ let tempIndex = 1
463
+ //如果前一个单元格存在则循环
464
+ while (el) {
465
+ //获取单元格的colspan
466
+ const { colspan } = getCellSpanNumber(el)
467
+ //如果单元格是跨列的并且是跨当前单元格的
468
+ if (el.hasMarks() && !el.marks!['data-editify-merged'] && colspan > tempIndex) {
469
+ success = true
470
+ callback(el)
471
+ break
472
+ }
473
+ //不是则继续向上查找
474
+ else {
475
+ el = editor.getPreviousElement(el)
476
+ tempIndex++
477
+ }
478
+ }
479
+ return success
480
+ }
481
+ //单元格向上查找设置焦点
482
+ const queryUpSetRange = (_element: AlexElement, callback: (ele: AlexElement) => void) => {
483
+ //是否已查找到
484
+ let success = false
485
+ //单元格在行中的序列
486
+ const index = _element.parent!.children!.findIndex(item => item.isEqual(_element))
487
+ //获取前一行元素
488
+ let el = editor.getPreviousElement(_element.parent!)
489
+ let tempIndex = 1
490
+ //如果前一行元素存在则循环
491
+ while (el) {
492
+ //获取前一行中同列的单元格
493
+ const previousColumn = el.children![index]
494
+ //获取单元格的rowspan
495
+ const { rowspan } = getCellSpanNumber(previousColumn)
496
+ //如果单元格是跨行的并且是跨当前单元格的
497
+ if (previousColumn.hasMarks() && !previousColumn.marks!['data-editify-merged'] && rowspan > tempIndex) {
498
+ success = true
499
+ callback(previousColumn)
500
+ break
501
+ }
502
+ //不是则继续向上查找
503
+ else {
504
+ el = editor.getPreviousElement(el)
505
+ tempIndex++
506
+ }
282
507
  }
283
- if (element.marks!['colspan']) {
284
- delete element.marks!['colspan']
508
+ return success
509
+ }
510
+ //起点在该单元格下
511
+ if (element.isContains(editor.range.anchor.element)) {
512
+ const success = queryLeftSetRange(element, ele => {
513
+ editor.range!.anchor.moveToEnd(ele)
514
+ })
515
+ if (!success) {
516
+ queryUpSetRange(element, ele => {
517
+ editor.range!.anchor.moveToEnd(ele)
518
+ })
285
519
  }
286
520
  }
287
- //移除列的display样式
288
- if (element.hasStyles()) {
289
- if (element.styles!['display']) {
290
- delete element.styles!['display']
521
+ //终点在该单元格下
522
+ if (element.isContains(editor.range.focus.element)) {
523
+ const success = queryLeftSetRange(element, ele => {
524
+ editor.range!.focus.moveToEnd(ele)
525
+ })
526
+ if (!success) {
527
+ queryUpSetRange(element, ele => {
528
+ editor.range!.focus.moveToEnd(ele)
529
+ })
291
530
  }
292
531
  }
293
532
  }
@@ -300,7 +539,7 @@ export const tableHandle = function (editor: AlexEditor, element: AlexElement) {
300
539
  * @param highlight
301
540
  * @param languages
302
541
  */
303
- export const preHandle = function (editor: AlexEditor, element: AlexElement, highlight: boolean, languages: (string | LanguagesItemType)[]) {
542
+ export const preHandle = (editor: AlexEditor, element: AlexElement, highlight: boolean, languages: (string | LanguagesItemType)[]) => {
304
543
  //如果是代码块进行处理
305
544
  if (element.parsedom == 'pre') {
306
545
  const marks = {
@@ -365,7 +604,7 @@ export const preHandle = function (editor: AlexEditor, element: AlexElement, hig
365
604
  * @param editor
366
605
  * @param element
367
606
  */
368
- export const specialInblockHandle = function (editor: AlexEditor, element: AlexElement) {
607
+ export const specialInblockHandle = (editor: AlexEditor, element: AlexElement) => {
369
608
  if (element.hasChildren()) {
370
609
  element.children!.forEach(el => {
371
610
  if (isList(el, true) || isList(el, false) || isTask(el) || ['blockquote', 'pre', 'table', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'].includes(el.parsedom!)) {
package/src/core/tool.ts CHANGED
@@ -224,7 +224,7 @@ export type PluginType = (editifyInstance: ComponentInternalInstance, editTrans:
224
224
  * @param o2
225
225
  * @returns
226
226
  */
227
- export const mergeObject = function (o1: ObjectType, o2: ObjectType) {
227
+ export const mergeObject = (o1: ObjectType, o2: ObjectType) => {
228
228
  if (!DapCommon.isObject(o1) && DapCommon.isObject(o2)) {
229
229
  return null
230
230
  }
@@ -248,7 +248,7 @@ export const mergeObject = function (o1: ObjectType, o2: ObjectType) {
248
248
  * @param value
249
249
  * @returns
250
250
  */
251
- export const queryHasValue = function (obj: ObjectType, name: string, value?: string | number) {
251
+ export const queryHasValue = (obj: ObjectType, name: string, value?: string | number) => {
252
252
  //如果value不存在则判断是否拥有属性name
253
253
  if (value == null || value == undefined) {
254
254
  return obj.hasOwnProperty(name)
@@ -293,7 +293,7 @@ export const queryHasValue = function (obj: ObjectType, name: string, value?: st
293
293
  * @param data
294
294
  * @returns
295
295
  */
296
- export const cloneData = function (data: any) {
296
+ export const cloneData = (data: any) => {
297
297
  if (DapCommon.isObject(data) || Array.isArray(data)) {
298
298
  return JSON.parse(JSON.stringify(data))
299
299
  }
@@ -305,7 +305,7 @@ export const cloneData = function (data: any) {
305
305
  * @param editTrans
306
306
  * @returns
307
307
  */
308
- export const getButtonOptionsConfig = function (editTrans: (key: string) => any): ButtonOptionsConfigType {
308
+ export const getButtonOptionsConfig = (editTrans: (key: string) => any): ButtonOptionsConfigType => {
309
309
  return {
310
310
  //标题配置
311
311
  heading: [
@@ -506,7 +506,7 @@ export const getButtonOptionsConfig = function (editTrans: (key: string) => any)
506
506
  * @param editLocale
507
507
  * @returns
508
508
  */
509
- export const getToolbarConfig = function (editTrans: (key: string) => any, editLocale: LocaleType): ToolbarConfigType {
509
+ export const getToolbarConfig = (editTrans: (key: string) => any, editLocale: LocaleType): ToolbarConfigType => {
510
510
  return {
511
511
  //是否使用工具条
512
512
  use: true,
@@ -756,7 +756,7 @@ export const getToolbarConfig = function (editTrans: (key: string) => any, editL
756
756
  * @param editLocale
757
757
  * @returns
758
758
  */
759
- export const getMenuConfig = function (editTrans: (key: string) => any, editLocale: LocaleType): MenuConfigType {
759
+ export const getMenuConfig = (editTrans: (key: string) => any, editLocale: LocaleType): MenuConfigType => {
760
760
  return {
761
761
  //是否使用菜单栏
762
762
  use: true,
@@ -232,6 +232,10 @@
232
232
  cursor: col-resize;
233
233
  user-select: none;
234
234
  }
235
+
236
+ &[data-editify-merged] {
237
+ display: none;
238
+ }
235
239
  }
236
240
  }
237
241
  }
@@ -23,7 +23,7 @@ import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, pro
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
25
  import { mergeObject, getToolbarConfig, getMenuConfig, MenuConfigType, ObjectType, ToolbarConfigType, PluginResultType } from '../core/tool'
26
- import { parseList, orderdListHandle, commonElementHandle, tableHandle, preHandle, specialInblockHandle } from '../core/rule'
26
+ import { parseList, orderdListHandle, commonElementHandle, tableThTdHandle, tableFormatHandle, tableRangeMergedHandle, preHandle, specialInblockHandle } from '../core/rule'
27
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'
@@ -287,7 +287,13 @@ const createEditor = () => {
287
287
  commonElementHandle(editor.value!, el)
288
288
  },
289
289
  el => {
290
- tableHandle(editor.value!, el)
290
+ tableThTdHandle(editor.value!, el)
291
+ },
292
+ el => {
293
+ tableFormatHandle(editor.value!, el)
294
+ },
295
+ el => {
296
+ tableRangeMergedHandle(editor.value!, el)
291
297
  },
292
298
  el => {
293
299
  preHandle(editor.value!, el, !!(toolbarConfig.value?.use && toolbarConfig.value?.codeBlock?.languages?.show), <(string | LanguagesItemType)[]>toolbarConfig.value?.codeBlock?.languages?.options)
@@ -521,6 +527,18 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
521
527
  if (el.parsedom == 'div' && el.marks!['data-editify-task']) {
522
528
  marks['data-editify-task'] = el.marks!['data-editify-task']
523
529
  }
530
+ //表格单元格colspan属性保留
531
+ if (['td', 'th'].includes(el.parsedom!) && el.marks!['colspan']) {
532
+ marks['colspan'] = el.marks!['colspan']
533
+ }
534
+ //表格单元格rowspan属性保留
535
+ if (['td', 'th'].includes(el.parsedom!) && el.marks!['rowspan']) {
536
+ marks['rowspan'] = el.marks!['rowspan']
537
+ }
538
+ //表格单元格被合并属性保留
539
+ if (['td', 'th'].includes(el.parsedom!) && el.marks!['data-editify-merged']) {
540
+ marks['data-editify-merged'] = el.marks!['data-editify-merged']
541
+ }
524
542
  }
525
543
  //处理需要保留的样式
526
544
  if (el.hasStyles()) {
@@ -1,3 +1,19 @@
1
+ .editify-icon-merge-cells-up:before {
2
+ content: '\e73e';
3
+ }
4
+
5
+ .editify-icon-merge-cells-left:before {
6
+ content: '\e741';
7
+ }
8
+
9
+ .editify-icon-merge-cells-right:before {
10
+ content: '\e73f';
11
+ }
12
+
13
+ .editify-icon-merge-cells-down:before {
14
+ content: '\e740';
15
+ }
16
+
1
17
  .editify-icon-mathformula:before {
2
18
  content: '\e616';
3
19
  }
Binary file
Binary file
package/src/index.ts CHANGED
@@ -9,17 +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
+ export type { ElementMatchConfigType } from './core/function'
13
13
 
14
14
  //导出编辑器操作方法
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
+ 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, insertSeparator } from './core/function'
16
16
 
17
17
  //安装函数
18
18
  const install: FunctionPlugin = (app: App) => {
19
19
  app.component(Editify.name!, Editify)
20
20
  }
21
21
  //版本号
22
- const version = '0.1.43'
22
+ const version = '0.1.44'
23
23
 
24
24
  //导出AlexElement元素
25
25
  export { AlexElement } from 'alex-editor'
@@ -9,6 +9,10 @@ export const en_US: ObjectType = {
9
9
  insertColumnRight: 'Insert column backward',
10
10
  deleteRow: 'Delete rows',
11
11
  deleteColumn: 'Delete column',
12
+ mergeCellsLeft: 'Merge cells to the left',
13
+ mergeCellsRight: 'Merge cells to the right',
14
+ mergeCellsUp: 'Merge cells up',
15
+ mergeCellsDown: 'Merge cells down',
12
16
  deleteTable: 'Delete table',
13
17
  selectLanguages: 'Select language',
14
18
  autoRecognize: 'Auto',
@@ -9,6 +9,10 @@ export const zh_CN: ObjectType = {
9
9
  insertColumnRight: '向后插入列',
10
10
  deleteRow: '删除行',
11
11
  deleteColumn: '删除列',
12
+ mergeCellsLeft: '向左合并单元格',
13
+ mergeCellsRight: '向右合并单元格',
14
+ mergeCellsUp: '向上合并单元格',
15
+ mergeCellsDown: '向下合并单元格',
12
16
  deleteTable: '删除表格',
13
17
  selectLanguages: '选择语言',
14
18
  autoRecognize: '自动识别',
@@ -1,48 +0,0 @@
1
- // vite.config.ts
2
- import { defineConfig } from "file:///Users/lingkai/Desktop/%E5%89%8D%E7%AB%AF%E5%BA%93/vue-editify/node_modules/vite/dist/node/index.js";
3
- import vue from "file:///Users/lingkai/Desktop/%E5%89%8D%E7%AB%AF%E5%BA%93/vue-editify/node_modules/@vitejs/plugin-vue/dist/index.mjs";
4
- import dts from "file:///Users/lingkai/Desktop/%E5%89%8D%E7%AB%AF%E5%BA%93/vue-editify/node_modules/vite-plugin-dts/dist/index.mjs";
5
- import path from "path";
6
- var __vite_injected_original_dirname = "/Users/lingkai/Desktop/\u524D\u7AEF\u5E93/vue-editify";
7
- var vite_config_default = defineConfig({
8
- plugins: [vue(), dts()],
9
- build: {
10
- //打包后的目录名称
11
- outDir: "lib",
12
- minify: "terser",
13
- lib: {
14
- entry: path.resolve(__vite_injected_original_dirname, "src/index.ts"),
15
- name: "editify",
16
- fileName: (format) => `editify.${format}.js`
17
- },
18
- rollupOptions: {
19
- // 确保外部化处理那些你不想打包进库的依赖
20
- external: ["vue"],
21
- output: {
22
- // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
23
- globals: {
24
- vue: "Vue"
25
- },
26
- exports: "named"
27
- }
28
- },
29
- sourcemap: false
30
- //是否构建source map 文件
31
- },
32
- css: {
33
- preprocessorOptions: {
34
- less: {
35
- // 使用 less 编写样式的 UI 库(如 antd)时建议加入这个设置
36
- javascriptEnabled: true,
37
- additionalData: `@import "src/css/base.less";`
38
- }
39
- }
40
- },
41
- server: {
42
- host: "0.0.0.0"
43
- }
44
- });
45
- export {
46
- vite_config_default as default
47
- };
48
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvbGluZ2thaS9EZXNrdG9wL1x1NTI0RFx1N0FFRlx1NUU5My92dWUtZWRpdGlmeVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL2xpbmdrYWkvRGVza3RvcC9cdTUyNERcdTdBRUZcdTVFOTMvdnVlLWVkaXRpZnkvdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL1VzZXJzL2xpbmdrYWkvRGVza3RvcC8lRTUlODklOEQlRTclQUIlQUYlRTUlQkElOTMvdnVlLWVkaXRpZnkvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tICd2aXRlJ1xuaW1wb3J0IHZ1ZSBmcm9tICdAdml0ZWpzL3BsdWdpbi12dWUnXG5pbXBvcnQgZHRzIGZyb20gJ3ZpdGUtcGx1Z2luLWR0cydcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG5cdHBsdWdpbnM6IFt2dWUoKSwgZHRzKCldLFxuXHRidWlsZDoge1xuXHRcdC8vXHU2MjUzXHU1MzA1XHU1NDBFXHU3Njg0XHU3NkVFXHU1RjU1XHU1NDBEXHU3OUYwXG5cdFx0b3V0RGlyOiAnbGliJyxcblx0XHRtaW5pZnk6ICd0ZXJzZXInLFxuXHRcdGxpYjoge1xuXHRcdFx0ZW50cnk6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICdzcmMvaW5kZXgudHMnKSxcblx0XHRcdG5hbWU6ICdlZGl0aWZ5Jyxcblx0XHRcdGZpbGVOYW1lOiBmb3JtYXQgPT4gYGVkaXRpZnkuJHtmb3JtYXR9LmpzYFxuXHRcdH0sXG5cdFx0cm9sbHVwT3B0aW9uczoge1xuXHRcdFx0Ly8gXHU3ODZFXHU0RkREXHU1OTE2XHU5MEU4XHU1MzE2XHU1OTA0XHU3NDA2XHU5MEEzXHU0RTlCXHU0RjYwXHU0RTBEXHU2MEYzXHU2MjUzXHU1MzA1XHU4RkRCXHU1RTkzXHU3Njg0XHU0RjlEXHU4RDU2XG5cdFx0XHRleHRlcm5hbDogWyd2dWUnXSxcblx0XHRcdG91dHB1dDoge1xuXHRcdFx0XHQvLyBcdTU3MjggVU1EIFx1Njc4NFx1NUVGQVx1NkEyMVx1NUYwRlx1NEUwQlx1NEUzQVx1OEZEOVx1NEU5Qlx1NTkxNlx1OTBFOFx1NTMxNlx1NzY4NFx1NEY5RFx1OEQ1Nlx1NjNEMFx1NEY5Qlx1NEUwMFx1NEUyQVx1NTE2OFx1NUM0MFx1NTNEOFx1OTFDRlxuXHRcdFx0XHRnbG9iYWxzOiB7XG5cdFx0XHRcdFx0dnVlOiAnVnVlJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRleHBvcnRzOiAnbmFtZWQnXG5cdFx0XHR9XG5cdFx0fSxcblx0XHRzb3VyY2VtYXA6IGZhbHNlIC8vXHU2NjJGXHU1NDI2XHU2Nzg0XHU1RUZBc291cmNlIG1hcCBcdTY1ODdcdTRFRjZcblx0fSxcblx0Y3NzOiB7XG5cdFx0cHJlcHJvY2Vzc29yT3B0aW9uczoge1xuXHRcdFx0bGVzczoge1xuXHRcdFx0XHQvLyBcdTRGN0ZcdTc1MjggbGVzcyBcdTdGMTZcdTUxOTlcdTY4MzdcdTVGMEZcdTc2ODQgVUkgXHU1RTkzXHVGRjA4XHU1OTgyIGFudGRcdUZGMDlcdTY1RjZcdTVFRkFcdThCQUVcdTUyQTBcdTUxNjVcdThGRDlcdTRFMkFcdThCQkVcdTdGNkVcblx0XHRcdFx0amF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXG5cdFx0XHRcdGFkZGl0aW9uYWxEYXRhOiBgQGltcG9ydCBcInNyYy9jc3MvYmFzZS5sZXNzXCI7YFxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0c2VydmVyOiB7XG5cdFx0aG9zdDogJzAuMC4wLjAnXG5cdH1cbn0pXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQTRULFNBQVMsb0JBQW9CO0FBQ3pWLE9BQU8sU0FBUztBQUNoQixPQUFPLFNBQVM7QUFDaEIsT0FBTyxVQUFVO0FBSGpCLElBQU0sbUNBQW1DO0FBS3pDLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzNCLFNBQVMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQUEsRUFDdEIsT0FBTztBQUFBO0FBQUEsSUFFTixRQUFRO0FBQUEsSUFDUixRQUFRO0FBQUEsSUFDUixLQUFLO0FBQUEsTUFDSixPQUFPLEtBQUssUUFBUSxrQ0FBVyxjQUFjO0FBQUEsTUFDN0MsTUFBTTtBQUFBLE1BQ04sVUFBVSxZQUFVLFdBQVcsTUFBTTtBQUFBLElBQ3RDO0FBQUEsSUFDQSxlQUFlO0FBQUE7QUFBQSxNQUVkLFVBQVUsQ0FBQyxLQUFLO0FBQUEsTUFDaEIsUUFBUTtBQUFBO0FBQUEsUUFFUCxTQUFTO0FBQUEsVUFDUixLQUFLO0FBQUEsUUFDTjtBQUFBLFFBQ0EsU0FBUztBQUFBLE1BQ1Y7QUFBQSxJQUNEO0FBQUEsSUFDQSxXQUFXO0FBQUE7QUFBQSxFQUNaO0FBQUEsRUFDQSxLQUFLO0FBQUEsSUFDSixxQkFBcUI7QUFBQSxNQUNwQixNQUFNO0FBQUE7QUFBQSxRQUVMLG1CQUFtQjtBQUFBLFFBQ25CLGdCQUFnQjtBQUFBLE1BQ2pCO0FBQUEsSUFDRDtBQUFBLEVBQ0Q7QUFBQSxFQUNBLFFBQVE7QUFBQSxJQUNQLE1BQU07QUFBQSxFQUNQO0FBQ0QsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K