vue-editify 0.1.40 → 0.1.41

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/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>