vue-editify 0.1.44 → 0.1.46

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.46",
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",
@@ -263,8 +263,9 @@
263
263
  height: auto;
264
264
  border-radius: 2px;
265
265
  vertical-align: text-bottom;
266
- margin: 0 2px;
266
+ margin: 0;
267
267
  max-width: 100%;
268
+ min-width: 100px;
268
269
  }
269
270
  //视频样式
270
271
  :deep(video) {
@@ -275,8 +276,9 @@
275
276
  vertical-align: text-bottom;
276
277
  background-color: #000;
277
278
  object-fit: contain;
278
- margin: 0 2px;
279
+ margin: 0;
279
280
  max-width: 100%;
281
+ min-width: 100px;
280
282
  }
281
283
  //引用样式
282
284
  :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,163 @@ 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)) {
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) {
384
- return
396
+ const event = e as MouseEvent
397
+ const elm = e.target as HTMLElement
398
+ //如果鼠标在图片和视频上
399
+ if (DapElement.isContains(contentRef.value!, elm) && ['img', 'video'].includes(elm.tagName.toLocaleLowerCase())) {
400
+ const rect = DapElement.getElementBounding(elm)
401
+ //在可拖拽范围内改变鼠标样式
402
+ if (event.pageX >= Math.abs(rect.left + elm.offsetWidth - 10) && event.pageX <= Math.abs(rect.left + elm.offsetWidth)) {
403
+ elm.style.cursor = 'col-resize'
404
+ } else {
405
+ elm.style.cursor = ''
406
+ }
385
407
  }
386
- const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
387
- if (tables.length != 1) {
408
+ if (!resizeParams.value.element) {
388
409
  return
389
410
  }
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
411
+ //表格列宽拖拽
412
+ if (resizeParams.value.element.parsedom == 'td') {
413
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
414
+ if (tables.length != 1) {
415
+ return
416
+ }
417
+ const colgroup = tables[0].children!.find(item => {
418
+ return item.parsedom == 'colgroup'
419
+ })!
420
+ const index = resizeParams.value.element.parent!.children!.findIndex(el => {
421
+ return el.isEqual(resizeParams.value.element!)
422
+ })
423
+ const width = `${resizeParams.value.element.elm!.offsetWidth + event.pageX - resizeParams.value.start}`
424
+ colgroup.children![index].marks!['width'] = width
425
+ colgroup.children![index].elm!.setAttribute('width', width)
426
+ resizeParams.value.start = event.pageX
427
+ }
428
+ //图片视频拖拽改变宽度
429
+ else if (['img', 'video'].includes(resizeParams.value.element.parsedom!)) {
430
+ const width = `${resizeParams.value.element.elm!.offsetWidth + event.pageX - resizeParams.value.start}px`
431
+ if (resizeParams.value.element.hasStyles()) {
432
+ resizeParams.value.element.styles!['width'] = width
433
+ } else {
434
+ resizeParams.value.element.styles = {
435
+ width: width
436
+ }
437
+ }
438
+ resizeParams.value.element.elm!.style.width = width
439
+ //视频宽度改变的同时需要设置高度
440
+ if (resizeParams.value.element.parsedom == 'video') {
441
+ setVideoHeight()
442
+ }
443
+ resizeParams.value.start = event.pageX
444
+ }
400
445
  }
401
- //鼠标在页面松开:处理表格拖拽改变列宽
446
+ //鼠标在页面松开:处理表格拖拽改变列宽、拖拽改变图片视频宽度
402
447
  const documentMouseUp = () => {
403
448
  if (props.disabled) {
404
449
  return
405
450
  }
406
- if (!tableColumnResizeParams.value.element) {
451
+ if (!resizeParams.value.element) {
407
452
  return
408
453
  }
409
- const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
410
- if (tables.length != 1) {
411
- return
454
+ //表格列宽拖拽
455
+ if (resizeParams.value.element.parsedom == 'td') {
456
+ const tables = getMatchElementsByRange(editor.value!, dataRangeCaches.value, { parsedom: 'table' })
457
+ if (tables.length != 1) {
458
+ return
459
+ }
460
+ const colgroup = tables[0].children!.find(item => {
461
+ return item.parsedom == 'colgroup'
462
+ })!
463
+ const index = resizeParams.value.element.parent!.children!.findIndex(el => {
464
+ return el.isEqual(resizeParams.value.element!)
465
+ })
466
+ const width = parseFloat(colgroup.children![index].marks!['width'])
467
+ if (!isNaN(width)) {
468
+ colgroup.children![index].marks!['width'] = `${Number(((width / resizeParams.value.element.parent!.elm!.offsetWidth) * 100).toFixed(2))}%`
469
+ editor.value!.formatElementStack()
470
+ editor.value!.domRender()
471
+ editor.value!.rangeRender()
472
+ }
473
+ resizeParams.value.element = null
474
+ resizeParams.value.start = 0
412
475
  }
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()
476
+ //图片视频拖拽改变宽度
477
+ else if (['img', 'video'].includes(resizeParams.value.element.parsedom!)) {
478
+ const width = parseFloat(resizeParams.value.element.styles!['width'])
479
+ if (!isNaN(width)) {
480
+ if (resizeParams.value.element.hasStyles()) {
481
+ resizeParams.value.element.styles!['width'] = `${Number(((width / DapElement.width(contentRef.value!)) * 100).toFixed(2))}%`
482
+ } else {
483
+ resizeParams.value.element.styles = {
484
+ width: `${Number(((width / DapElement.width(contentRef.value!)) * 100).toFixed(2))}%`
485
+ }
486
+ }
487
+ editor.value!.formatElementStack()
488
+ editor.value!.domRender()
489
+ editor.value!.rangeRender()
490
+ }
491
+ resizeParams.value.element = null
492
+ resizeParams.value.start = 0
425
493
  }
426
- tableColumnResizeParams.value.element = null
427
- tableColumnResizeParams.value.start = 0
428
494
  }
429
495
  //鼠标点击页面:处理任务列表复选框勾选
430
496
  const documentClick = (e: Event) => {
431
497
  if (props.disabled) {
432
498
  return
433
499
  }
500
+ const elm = e.target as HTMLElement
501
+ const event = e as MouseEvent
434
502
  //鼠标在编辑器内点击
435
- if (DapElement.isContains(contentRef.value!, <HTMLElement>e.target)) {
436
- const elm = <HTMLElement>e.target
503
+ if (DapElement.isContains(contentRef.value!, elm)) {
437
504
  const key = DapData.get(elm, 'data-alex-editor-key')
438
505
  if (key) {
439
506
  const element = editor.value!.getElementByKey(key)!
@@ -441,7 +508,7 @@ const documentClick = (e: Event) => {
441
508
  if (isTask(element)) {
442
509
  const rect = DapElement.getElementBounding(elm)
443
510
  //在复选框范围内
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)) {
511
+ 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
512
  //取消勾选
446
513
  if (element.marks!['data-editify-task'] == 'checked') {
447
514
  element.marks!['data-editify-task'] = 'uncheck'
@@ -483,6 +550,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
483
550
  if (el.marks!['disabled']) {
484
551
  marks['disabled'] = el.marks!['disabled']
485
552
  }
553
+ //图片的alt属性保留
554
+ if (el.parsedom == 'img' && el.marks!['alt']) {
555
+ marks['alt'] = el.marks!['alt']
556
+ }
486
557
  //图片和视频的src属性保留
487
558
  if (['img', 'video'].includes(el.parsedom!) && el.marks!['src']) {
488
559
  marks['src'] = el.marks!['src']
@@ -527,6 +598,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
527
598
  if (el.parsedom == 'div' && el.marks!['data-editify-task']) {
528
599
  marks['data-editify-task'] = el.marks!['data-editify-task']
529
600
  }
601
+ //表格列宽属性保留
602
+ if (el.parsedom == 'col' && el.marks!['width']) {
603
+ marks['width'] = el.marks!['width']
604
+ }
530
605
  //表格单元格colspan属性保留
531
606
  if (['td', 'th'].includes(el.parsedom!) && el.marks!['colspan']) {
532
607
  marks['colspan'] = el.marks!['colspan']
@@ -542,6 +617,10 @@ const handleCustomHtmlPaste = async (elements: AlexElement[]) => {
542
617
  }
543
618
  //处理需要保留的样式
544
619
  if (el.hasStyles()) {
620
+ //图片和视频保留width样式
621
+ if (['img', 'video'].includes(el.parsedom!) && el.styles!['width']) {
622
+ styles['width'] = el.styles!['width']
623
+ }
545
624
  //块元素保留text-indent样式
546
625
  if ((el.isBlock() || el.isInblock()) && el.styles!['text-indent']) {
547
626
  styles['text-indent'] = el.styles!['text-indent']
@@ -649,10 +728,10 @@ const handleEditorClick = (e: Event) => {
649
728
  if (props.disabled || isSourceView.value) {
650
729
  return
651
730
  }
652
- const node = <HTMLElement>e.target
731
+ const elm = e.target as HTMLElement
653
732
  //点击的是图片或者视频
654
- if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
655
- const key = Number(node.getAttribute('data-editify-element'))
733
+ if (elm.nodeName.toLocaleLowerCase() == 'img' || elm.nodeName.toLocaleLowerCase() == 'video') {
734
+ const key = Number(elm.getAttribute('data-editify-element'))
656
735
  if (DapNumber.isNumber(key)) {
657
736
  const element = editor.value!.getElementByKey(key)!
658
737
  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.46'
23
23
 
24
24
  //导出AlexElement元素
25
25
  export { AlexElement } from 'alex-editor'