vue-editify 0.1.44 → 0.1.45

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.44",
3
+ "version": "0.1.45",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -17,7 +17,7 @@
17
17
  "lib": "vue-tsc && vite build"
18
18
  },
19
19
  "dependencies": {
20
- "alex-editor": "^1.4.7",
20
+ "alex-editor": "^1.4.8",
21
21
  "dap-util": "^1.5.4",
22
22
  "highlight.js": "^11.8.0",
23
23
  "katex": "^0.16.10",
@@ -265,6 +265,11 @@
265
265
  vertical-align: text-bottom;
266
266
  margin: 0 2px;
267
267
  max-width: 100%;
268
+ min-width: 100px;
269
+
270
+ &:hover {
271
+ cursor: pointer;
272
+ }
268
273
  }
269
274
  //视频样式
270
275
  :deep(video) {
@@ -277,6 +282,7 @@
277
282
  object-fit: contain;
278
283
  margin: 0 2px;
279
284
  max-width: 100%;
285
+ min-width: 100px;
280
286
  }
281
287
  //引用样式
282
288
  :deep(blockquote) {
@@ -28,7 +28,7 @@ import { isTask, elementToParagraph, getMatchElementsByRange, hasTableInRange, h
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'
31
- import { EditifyProps, EditifyTableColumnResizeParamsType, EditifyToolbarOptionsType } from './props'
31
+ import { EditifyProps, EditifyResizeParamsType, EditifyToolbarOptionsType } from './props'
32
32
  import { trans } from '../locale'
33
33
  import { LanguagesItemType } from '../hljs'
34
34
 
@@ -52,8 +52,8 @@ const isModelChange = ref<boolean>(false)
52
52
  const isInputChinese = ref<boolean>(false)
53
53
  //工具条和菜单栏判定延时器
54
54
  const rangeUpdateTimer = ref<any>(null)
55
- //表格列宽拖拽记录数据
56
- const tableColumnResizeParams = ref<EditifyTableColumnResizeParamsType>({
55
+ //拖拽记录数据
56
+ const resizeParams = ref<EditifyResizeParamsType>({
57
57
  element: null, //被拖拽的td
58
58
  start: 0 //水平方向起点位置
59
59
  })
@@ -344,96 +344,151 @@ const setVideoHeight = () => {
344
344
  video.style.height = video.offsetWidth / props.videoRatio + 'px'
345
345
  })
346
346
  }
347
- //鼠标在页面按下:处理表格拖拽改变列宽和菜单栏是否使用判断
347
+ //鼠标在页面按下:处理表格拖拽改变列宽、拖拽改变图片视频宽度和菜单栏是否使用判断
348
348
  const documentMouseDown = (e: Event) => {
349
349
  if (props.disabled) {
350
350
  return
351
351
  }
352
+ const elm = e.target as HTMLElement
353
+ const event = e as MouseEvent
352
354
  //鼠标在编辑器内按下
353
- if (DapElement.isContains(contentRef.value!, <HTMLElement>e.target)) {
354
- const elm = <HTMLElement>e.target
355
+ if (DapElement.isContains(contentRef.value!, elm)) {
355
356
  const key = DapData.get(elm, 'data-alex-editor-key')
356
357
  if (key) {
357
358
  const element = editor.value!.getElementByKey(key)
358
- if (element && element.parsedom == 'td') {
359
- const length = element.parent!.children!.length
360
- //最后一个td不设置
361
- if (element.parent!.children![length - 1].isEqual(element)) {
362
- return
359
+ if (element) {
360
+ //如果是td则表示拖拽改变列宽
361
+ if (element.parsedom == 'td') {
362
+ const length = element.parent!.children!.length
363
+ //最后一个td不设置
364
+ if (element.parent!.children![length - 1].isEqual(element)) {
365
+ return
366
+ }
367
+ const rect = DapElement.getElementBounding(elm)
368
+ //在可拖拽范围内
369
+ if (event.pageX >= Math.abs(rect.left + elm.offsetWidth - 5) && event.pageX <= Math.abs(rect.left + elm.offsetWidth + 5)) {
370
+ resizeParams.value.element = element
371
+ resizeParams.value.start = event.pageX
372
+ }
363
373
  }
364
- const rect = DapElement.getElementBounding(elm)
365
- //在可拖拽范围内
366
- if ((<MouseEvent>e).pageX >= Math.abs(rect.left + elm.offsetWidth - 5) && (<MouseEvent>e).pageX <= Math.abs(rect.left + elm.offsetWidth + 5)) {
367
- tableColumnResizeParams.value.element = element
368
- tableColumnResizeParams.value.start = (<MouseEvent>e).pageX
374
+ //如果是img或者video则表示拖拽改变图片视频宽度
375
+ else if (['img', 'video'].includes(element.parsedom!)) {
376
+ const rect = DapElement.getElementBounding(elm)
377
+ //在可拖拽范围内
378
+ if ((event.pageX >= Math.abs(rect.left + elm.offsetWidth - 10) && event.pageX <= Math.abs(rect.left + elm.offsetWidth)) || (event.pageX >= Math.abs(rect.left) && event.pageX <= Math.abs(rect.left + 10))) {
379
+ resizeParams.value.element = element
380
+ resizeParams.value.start = event.pageX
381
+ }
369
382
  }
370
383
  }
371
384
  }
372
385
  }
373
386
  //如果点击了除编辑器外的地方,菜单栏不可使用
374
- if (!DapElement.isContains(elRef.value!, <HTMLElement>e.target) && !isSourceView.value) {
387
+ if (!DapElement.isContains(elRef.value!, elm) && !isSourceView.value) {
375
388
  canUseMenu.value = false
376
389
  }
377
390
  }
378
- //鼠标在页面移动:处理表格拖拽改变列宽
391
+ //鼠标在页面移动:处理表格拖拽改变列宽、拖拽改变图片视频宽度
379
392
  const documentMouseMove = (e: Event) => {
380
393
  if (props.disabled) {
381
394
  return
382
395
  }
383
- if (!tableColumnResizeParams.value.element) {
396
+ if (!resizeParams.value.element) {
384
397
  return
385
398
  }
386
- const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
387
- if (tables.length != 1) {
388
- return
399
+ const event = e as MouseEvent
400
+ //表格列宽拖拽
401
+ if (resizeParams.value.element.parsedom == 'td') {
402
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
403
+ if (tables.length != 1) {
404
+ return
405
+ }
406
+ const colgroup = tables[0].children!.find(item => {
407
+ return item.parsedom == 'colgroup'
408
+ })!
409
+ const index = resizeParams.value.element.parent!.children!.findIndex(el => {
410
+ return el.isEqual(resizeParams.value.element!)
411
+ })
412
+ const width = `${resizeParams.value.element.elm!.offsetWidth + event.pageX - resizeParams.value.start}`
413
+ colgroup.children![index].marks!['width'] = width
414
+ colgroup.children![index].elm!.setAttribute('width', width)
415
+ resizeParams.value.start = event.pageX
416
+ }
417
+ //图片视频拖拽改变宽度
418
+ else if (['img', 'video'].includes(resizeParams.value.element.parsedom!)) {
419
+ const width = `${resizeParams.value.element.elm!.offsetWidth + event.pageX - resizeParams.value.start}px`
420
+ if (resizeParams.value.element.hasStyles()) {
421
+ resizeParams.value.element.styles!['width'] = width
422
+ } else {
423
+ resizeParams.value.element.styles = {
424
+ width: width
425
+ }
426
+ }
427
+ resizeParams.value.element.elm!.style.width = width
428
+ if (resizeParams.value.element.parsedom == 'video') {
429
+ setVideoHeight()
430
+ }
431
+ resizeParams.value.start = event.pageX
389
432
  }
390
- const colgroup = tables[0].children!.find(item => {
391
- return item.parsedom == 'colgroup'
392
- })!
393
- const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
394
- return el.isEqual(tableColumnResizeParams.value.element!)
395
- })
396
- const width = `${tableColumnResizeParams.value.element.elm!.offsetWidth + (<MouseEvent>e).pageX - tableColumnResizeParams.value.start}`
397
- colgroup.children![index].marks!['width'] = width
398
- colgroup.children![index].elm!.setAttribute('width', width)
399
- tableColumnResizeParams.value.start = (<MouseEvent>e).pageX
400
433
  }
401
- //鼠标在页面松开:处理表格拖拽改变列宽
434
+ //鼠标在页面松开:处理表格拖拽改变列宽、拖拽改变图片视频宽度
402
435
  const documentMouseUp = () => {
403
436
  if (props.disabled) {
404
437
  return
405
438
  }
406
- if (!tableColumnResizeParams.value.element) {
439
+ if (!resizeParams.value.element) {
407
440
  return
408
441
  }
409
- const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
410
- if (tables.length != 1) {
411
- return
442
+ //表格列宽拖拽
443
+ if (resizeParams.value.element.parsedom == 'td') {
444
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
445
+ if (tables.length != 1) {
446
+ return
447
+ }
448
+ const colgroup = tables[0].children!.find(item => {
449
+ return item.parsedom == 'colgroup'
450
+ })!
451
+ const index = resizeParams.value.element.parent!.children!.findIndex(el => {
452
+ return el.isEqual(resizeParams.value.element!)
453
+ })
454
+ const width = parseFloat(colgroup.children![index].marks!['width'])
455
+ if (!isNaN(width)) {
456
+ colgroup.children![index].marks!['width'] = `${Number(((width / resizeParams.value.element.parent!.elm!.offsetWidth) * 100).toFixed(2))}%`
457
+ editor.value!.formatElementStack()
458
+ editor.value!.domRender()
459
+ editor.value!.rangeRender()
460
+ }
461
+ resizeParams.value.element = null
462
+ resizeParams.value.start = 0
412
463
  }
413
- const colgroup = tables[0].children!.find(item => {
414
- return item.parsedom == 'colgroup'
415
- })!
416
- const index = tableColumnResizeParams.value.element.parent!.children!.findIndex(el => {
417
- return el.isEqual(tableColumnResizeParams.value.element!)
418
- })
419
- const width = Number(colgroup.children![index].marks!['width'])
420
- if (!isNaN(width)) {
421
- colgroup.children![index].marks!['width'] = `${Number(((width / tableColumnResizeParams.value.element.parent!.elm!.offsetWidth) * 100).toFixed(2))}%`
422
- editor.value!.formatElementStack()
423
- editor.value!.domRender()
424
- editor.value!.rangeRender()
464
+ //图片视频拖拽改变宽度
465
+ else if (['img', 'video'].includes(resizeParams.value.element.parsedom!)) {
466
+ const width = parseFloat(resizeParams.value.element.styles!['width'])
467
+ if (!isNaN(width)) {
468
+ if (resizeParams.value.element.hasStyles()) {
469
+ resizeParams.value.element.styles!['width'] = `${Number(((width / DapElement.width(contentRef.value!)) * 100).toFixed(2))}%`
470
+ } else {
471
+ resizeParams.value.element.styles = {
472
+ width: `${Number(((width / DapElement.width(contentRef.value!)) * 100).toFixed(2))}%`
473
+ }
474
+ }
475
+ editor.value!.formatElementStack()
476
+ editor.value!.domRender()
477
+ editor.value!.rangeRender()
478
+ }
479
+ resizeParams.value.element = null
480
+ resizeParams.value.start = 0
425
481
  }
426
- tableColumnResizeParams.value.element = null
427
- tableColumnResizeParams.value.start = 0
428
482
  }
429
483
  //鼠标点击页面:处理任务列表复选框勾选
430
484
  const documentClick = (e: Event) => {
431
485
  if (props.disabled) {
432
486
  return
433
487
  }
488
+ const elm = e.target as HTMLElement
489
+ const event = e as MouseEvent
434
490
  //鼠标在编辑器内点击
435
- if (DapElement.isContains(contentRef.value!, <HTMLElement>e.target)) {
436
- const elm = <HTMLElement>e.target
491
+ if (DapElement.isContains(contentRef.value!, elm)) {
437
492
  const key = DapData.get(elm, 'data-alex-editor-key')
438
493
  if (key) {
439
494
  const element = editor.value!.getElementByKey(key)!
@@ -441,7 +496,7 @@ const documentClick = (e: Event) => {
441
496
  if (isTask(element)) {
442
497
  const rect = DapElement.getElementBounding(elm)
443
498
  //在复选框范围内
444
- if ((<MouseEvent>e).pageX >= Math.abs(rect.left) && (<MouseEvent>e).pageX <= Math.abs(rect.left + 16) && (<MouseEvent>e).pageY >= Math.abs(rect.top + elm.offsetHeight / 2 - 8) && (<MouseEvent>e).pageY <= Math.abs(rect.top + elm.offsetHeight / 2 + 8)) {
499
+ if (event.pageX >= Math.abs(rect.left) && event.pageX <= Math.abs(rect.left + 16) && event.pageY >= Math.abs(rect.top + elm.offsetHeight / 2 - 8) && event.pageY <= Math.abs(rect.top + elm.offsetHeight / 2 + 8)) {
445
500
  //取消勾选
446
501
  if (element.marks!['data-editify-task'] == 'checked') {
447
502
  element.marks!['data-editify-task'] = 'uncheck'
@@ -483,6 +538,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
483
538
  if (el.marks!['disabled']) {
484
539
  marks['disabled'] = el.marks!['disabled']
485
540
  }
541
+ //图片的alt属性保留
542
+ if (el.parsedom == 'img' && el.marks!['alt']) {
543
+ marks['alt'] = el.marks!['alt']
544
+ }
486
545
  //图片和视频的src属性保留
487
546
  if (['img', 'video'].includes(el.parsedom!) && el.marks!['src']) {
488
547
  marks['src'] = el.marks!['src']
@@ -527,6 +586,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
527
586
  if (el.parsedom == 'div' && el.marks!['data-editify-task']) {
528
587
  marks['data-editify-task'] = el.marks!['data-editify-task']
529
588
  }
589
+ //表格列宽属性保留
590
+ if (el.parsedom == 'col' && el.marks!['width']) {
591
+ marks['width'] = el.marks!['width']
592
+ }
530
593
  //表格单元格colspan属性保留
531
594
  if (['td', 'th'].includes(el.parsedom!) && el.marks!['colspan']) {
532
595
  marks['colspan'] = el.marks!['colspan']
@@ -542,6 +605,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
542
605
  }
543
606
  //处理需要保留的样式
544
607
  if (el.hasStyles()) {
608
+ //图片和视频保留width样式
609
+ if (['img', 'video'].includes(el.parsedom!) && el.styles!['width']) {
610
+ styles['width'] = el.styles!['width']
611
+ }
545
612
  //块元素保留text-indent样式
546
613
  if ((el.isBlock() || el.isInblock()) && el.styles!['text-indent']) {
547
614
  styles['text-indent'] = el.styles!['text-indent']
@@ -649,10 +716,10 @@ const handleEditorClick = (e: Event) => {
649
716
  if (props.disabled || isSourceView.value) {
650
717
  return
651
718
  }
652
- const node = <HTMLElement>e.target
719
+ const elm = e.target as HTMLElement
653
720
  //点击的是图片或者视频
654
- if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
655
- const key = Number(node.getAttribute('data-editify-element'))
721
+ if (elm.nodeName.toLocaleLowerCase() == 'img' || elm.nodeName.toLocaleLowerCase() == 'video') {
722
+ const key = Number(elm.getAttribute('data-editify-element'))
656
723
  if (DapNumber.isNumber(key)) {
657
724
  const element = editor.value!.getElementByKey(key)!
658
725
  if (!editor.value!.range) {
@@ -4,7 +4,7 @@ import { PluginType, MenuConfigType, ObjectType, ToolbarConfigType } from '../co
4
4
  import { AlexElement } from 'alex-editor'
5
5
  import { LocaleType } from '../locale'
6
6
 
7
- export type EditifyTableColumnResizeParamsType = {
7
+ export type EditifyResizeParamsType = {
8
8
  element: AlexElement | null
9
9
  start: number
10
10
  }
Binary file
Binary file
package/src/index.ts CHANGED
@@ -19,7 +19,7 @@ const install: FunctionPlugin = (app: App) => {
19
19
  app.component(Editify.name!, Editify)
20
20
  }
21
21
  //版本号
22
- const version = '0.1.44'
22
+ const version = '0.1.45'
23
23
 
24
24
  //导出AlexElement元素
25
25
  export { AlexElement } from 'alex-editor'