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/examples/App.vue +1 -1
- package/lib/editify/props.d.ts +1 -1
- package/lib/editify.es.js +130 -61
- package/lib/editify.umd.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/style.css +1 -1
- package/package.json +2 -2
- package/src/editify/editify.less +4 -2
- package/src/editify/editify.vue +136 -57
- package/src/editify/props.ts +1 -1
- package/src/icon/iconfont.ttf +0 -0
- package/src/icon/iconfont.woff +0 -0
- package/src/index.ts +1 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "vue-editify",
|
3
|
-
"version": "0.1.
|
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.
|
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",
|
package/src/editify/editify.less
CHANGED
@@ -263,8 +263,9 @@
|
|
263
263
|
height: auto;
|
264
264
|
border-radius: 2px;
|
265
265
|
vertical-align: text-bottom;
|
266
|
-
margin: 0
|
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
|
279
|
+
margin: 0;
|
279
280
|
max-width: 100%;
|
281
|
+
min-width: 100px;
|
280
282
|
}
|
281
283
|
//引用样式
|
282
284
|
:deep(blockquote) {
|
package/src/editify/editify.vue
CHANGED
@@ -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,
|
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
|
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!,
|
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
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
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
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
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!,
|
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
|
-
|
384
|
-
|
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
|
-
|
387
|
-
if (tables.length != 1) {
|
408
|
+
if (!resizeParams.value.element) {
|
388
409
|
return
|
389
410
|
}
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
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 (!
|
451
|
+
if (!resizeParams.value.element) {
|
407
452
|
return
|
408
453
|
}
|
409
|
-
|
410
|
-
if (
|
411
|
-
|
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
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
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!,
|
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 (
|
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
|
731
|
+
const elm = e.target as HTMLElement
|
653
732
|
//点击的是图片或者视频
|
654
|
-
if (
|
655
|
-
const key = Number(
|
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) {
|
package/src/editify/props.ts
CHANGED
@@ -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
|
7
|
+
export type EditifyResizeParamsType = {
|
8
8
|
element: AlexElement | null
|
9
9
|
start: number
|
10
10
|
}
|
package/src/icon/iconfont.ttf
CHANGED
Binary file
|
package/src/icon/iconfont.woff
CHANGED
Binary file
|