vue-editify 0.0.34 → 0.0.36
Sign up to get free protection for your applications and to get access to all the features.
- package/examples/App.vue +65 -3
- package/lib/editify.es.js +54 -23
- package/lib/editify.umd.js +1 -1
- package/lib/style.css +1 -1
- package/package.json +2 -1
- package/src/Editify.vue +27 -7
- package/src/core/index.js +15 -15
- package/src/index.js +1 -1
package/examples/App.vue
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
<template>
|
2
2
|
<div style="padding: 100px 50px 50px 50px">
|
3
|
-
<editify v-model="value" placeholder="请输入正文内容..." allow-paste-html border @change="change" :menu="menuConfig" ref="editify" height="400px"></editify>
|
3
|
+
<editify v-model="value" placeholder="请输入正文内容..." allow-paste-html border @change="change" :menu="menuConfig" ref="editify" height="400px" @after-render="afterRender" :paste-keep-marks="{ 'data-zip': ['span'] }" :custom-parse-node="parseNode"></editify>
|
4
4
|
</div>
|
5
5
|
</template>
|
6
6
|
<script>
|
7
|
+
import { AlexElement } from '../src'
|
7
8
|
import { h } from 'vue'
|
9
|
+
import Dap from 'dap-util'
|
8
10
|
export default {
|
9
11
|
name: 'App',
|
10
12
|
data() {
|
11
13
|
return {
|
12
|
-
value: '<p><span>这是一个基于 </span><
|
14
|
+
value: '<p><span>这是一个基于 </span><code>Vue3 + alex-editor</code><span> 构建的一套</span><span style="font-weight: bold;">精美UI样式</span><span>的</span><span style="font-weight: bold;">开箱即用</span><span>的</span><span style="color: #ec1a0a;">富文本编辑器</span></p>',
|
13
15
|
menuConfig: {
|
14
16
|
//mode: 'inner',
|
15
17
|
sequence: {
|
16
|
-
alert: 100
|
18
|
+
alert: 100,
|
19
|
+
zip: 101
|
17
20
|
},
|
18
21
|
table: {
|
19
22
|
maxRows: 20,
|
@@ -23,6 +26,38 @@ export default {
|
|
23
26
|
show: true
|
24
27
|
},
|
25
28
|
extends: {
|
29
|
+
zip: {
|
30
|
+
title: '上传压缩包',
|
31
|
+
default: () => {
|
32
|
+
return h('span', {}, 'zip')
|
33
|
+
},
|
34
|
+
onOperate: () => {
|
35
|
+
//选择文件上传
|
36
|
+
const upload = document.createElement('input')
|
37
|
+
upload.setAttribute('type', 'file')
|
38
|
+
upload.setAttribute('accept', 'application/zip')
|
39
|
+
upload.onchange = async e => {
|
40
|
+
//获取到文件
|
41
|
+
const file = e.currentTarget.files[0]
|
42
|
+
if (file) {
|
43
|
+
//转成base64
|
44
|
+
const base64 = await Dap.file.dataFileToBase64(file)
|
45
|
+
//创建元素
|
46
|
+
const zipEle = new AlexElement('closed', 'span', { 'data-zip': 'true', contenteditable: 'false' }, null, null)
|
47
|
+
//插入编辑器
|
48
|
+
this.$refs.editify.editor.insertElement(zipEle)
|
49
|
+
//移动光标到新插入的元素
|
50
|
+
this.$refs.editify.editor.range.anchor.moveToStart(zipEle)
|
51
|
+
this.$refs.editify.editor.range.focus.moveToStart(zipEle)
|
52
|
+
//格式化
|
53
|
+
this.$refs.editify.editor.formatElementStack()
|
54
|
+
//渲染
|
55
|
+
this.$refs.editify.editor.domRender()
|
56
|
+
}
|
57
|
+
}
|
58
|
+
upload.click()
|
59
|
+
}
|
60
|
+
},
|
26
61
|
alert: {
|
27
62
|
title: '自定义菜单按钮',
|
28
63
|
leftBorder: true,
|
@@ -66,6 +101,23 @@ export default {
|
|
66
101
|
// }, 3000)
|
67
102
|
},
|
68
103
|
methods: {
|
104
|
+
afterRender() {
|
105
|
+
this.$refs.editify.$el.querySelectorAll('[data-zip]').forEach(el => {
|
106
|
+
el.onclick = function () {
|
107
|
+
const url = el.getAttribute('data-zip')
|
108
|
+
const a = document.createElement('a')
|
109
|
+
a.setAttribute('href', url)
|
110
|
+
a.setAttribute('download', 'download.zip')
|
111
|
+
a.click()
|
112
|
+
}
|
113
|
+
})
|
114
|
+
},
|
115
|
+
parseNode(ele) {
|
116
|
+
if (ele.hasMarks() && ele.marks['data-zip']) {
|
117
|
+
ele.type = 'closed'
|
118
|
+
}
|
119
|
+
return ele
|
120
|
+
},
|
69
121
|
change() {
|
70
122
|
console.log(this.$refs.editify.textValue)
|
71
123
|
},
|
@@ -88,4 +140,14 @@ body {
|
|
88
140
|
height: 100%;
|
89
141
|
overflow: auto;
|
90
142
|
}
|
143
|
+
|
144
|
+
span[data-zip] {
|
145
|
+
display: inline-block;
|
146
|
+
width: 40px;
|
147
|
+
height: 40px;
|
148
|
+
background: url(https://www.ling0523.cn/images/image_0_1702456046669.png) no-repeat center;
|
149
|
+
background-size: cover;
|
150
|
+
cursor: pointer;
|
151
|
+
margin: 0 10px;
|
152
|
+
}
|
91
153
|
</style>
|
package/lib/editify.es.js
CHANGED
@@ -1844,7 +1844,9 @@ const initEditorOptions = (options) => {
|
|
1844
1844
|
//自定义视频粘贴方法
|
1845
1845
|
customVideoPaste: null,
|
1846
1846
|
//自定义处理不可编辑元素合并的逻辑
|
1847
|
-
customMerge: null
|
1847
|
+
customMerge: null,
|
1848
|
+
//自定义dom转为非文本元素的后续处理逻辑
|
1849
|
+
customParseNode: null
|
1848
1850
|
};
|
1849
1851
|
if (obj$1.common.isObject(options)) {
|
1850
1852
|
if (typeof options.disabled == "boolean") {
|
@@ -1883,6 +1885,9 @@ const initEditorOptions = (options) => {
|
|
1883
1885
|
if (typeof options.customMerge == "function") {
|
1884
1886
|
opts.customMerge = options.customMerge;
|
1885
1887
|
}
|
1888
|
+
if (typeof options.customParseNode == "function") {
|
1889
|
+
opts.customParseNode = options.customParseNode;
|
1890
|
+
}
|
1886
1891
|
}
|
1887
1892
|
return opts;
|
1888
1893
|
};
|
@@ -3258,6 +3263,7 @@ class AlexEditor {
|
|
3258
3263
|
this.customImagePaste = options.customImagePaste;
|
3259
3264
|
this.customVideoPaste = options.customVideoPaste;
|
3260
3265
|
this.customMerge = options.customMerge;
|
3266
|
+
this.customParseNode = options.customParseNode;
|
3261
3267
|
this.useClipboard = canUseClipboard();
|
3262
3268
|
this.history = new AlexHistory();
|
3263
3269
|
this.stack = this.parseHtml(this.value);
|
@@ -4251,6 +4257,9 @@ class AlexEditor {
|
|
4251
4257
|
}
|
4252
4258
|
});
|
4253
4259
|
}
|
4260
|
+
if (typeof this.customParseNode == "function") {
|
4261
|
+
element2 = this.customParseNode.apply(this, [element2]);
|
4262
|
+
}
|
4254
4263
|
return element2;
|
4255
4264
|
}
|
4256
4265
|
/**
|
@@ -15387,6 +15396,21 @@ const editorProps = {
|
|
15387
15396
|
menu: {
|
15388
15397
|
type: Object,
|
15389
15398
|
default: null
|
15399
|
+
},
|
15400
|
+
//dom转换时的额外处理
|
15401
|
+
customParseNode: {
|
15402
|
+
type: Function,
|
15403
|
+
default: null
|
15404
|
+
},
|
15405
|
+
//粘贴html时额外保留的标记(全部元素生效)
|
15406
|
+
pasteKeepMarks: {
|
15407
|
+
type: Object,
|
15408
|
+
default: null
|
15409
|
+
},
|
15410
|
+
//粘贴html时额外保留的样式(仅在非文本元素生效)
|
15411
|
+
pasteKeepStyles: {
|
15412
|
+
type: Object,
|
15413
|
+
default: null
|
15390
15414
|
}
|
15391
15415
|
};
|
15392
15416
|
const getColNumbers = (row) => {
|
@@ -15479,19 +15503,6 @@ const parseList = function(element2) {
|
|
15479
15503
|
}
|
15480
15504
|
}
|
15481
15505
|
};
|
15482
|
-
const parseCode = function(element2) {
|
15483
|
-
if (element2.parsedom == "code") {
|
15484
|
-
element2.parsedom = "span";
|
15485
|
-
const marks = {
|
15486
|
-
"data-editify-code": true
|
15487
|
-
};
|
15488
|
-
if (element2.hasMarks()) {
|
15489
|
-
Object.assign(element2.marks, marks);
|
15490
|
-
} else {
|
15491
|
-
element2.marks = marks;
|
15492
|
-
}
|
15493
|
-
}
|
15494
|
-
};
|
15495
15506
|
const mediaHandle = function(element2) {
|
15496
15507
|
if (element2.parsedom == "img" || element2.parsedom == "video" || element2.parsedom == "a") {
|
15497
15508
|
const marks = {
|
@@ -21186,7 +21197,7 @@ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
21186
21197
|
], 14, _hoisted_1$1);
|
21187
21198
|
}
|
21188
21199
|
const Menu = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1], ["__scopeId", "data-v-42f60b43"]]);
|
21189
|
-
const
|
21200
|
+
const Editify_vue_vue_type_style_index_0_scoped_8415c1dc_lang = "";
|
21190
21201
|
const _sfc_main = {
|
21191
21202
|
name: "editify",
|
21192
21203
|
props: { ...editorProps },
|
@@ -21312,7 +21323,6 @@ const _sfc_main = {
|
|
21312
21323
|
disabled: this.disabled,
|
21313
21324
|
renderRules: [
|
21314
21325
|
parseList,
|
21315
|
-
parseCode,
|
21316
21326
|
mediaHandle,
|
21317
21327
|
tableHandle,
|
21318
21328
|
(el) => {
|
@@ -21327,7 +21337,8 @@ const _sfc_main = {
|
|
21327
21337
|
allowPasteHtml: this.allowPasteHtml,
|
21328
21338
|
customImagePaste: this.customImagePaste,
|
21329
21339
|
customVideoPaste: this.customVideoPaste,
|
21330
|
-
customMerge: this.handleCustomMerge
|
21340
|
+
customMerge: this.handleCustomMerge,
|
21341
|
+
customParseNode: this.handleCustomParseNode
|
21331
21342
|
});
|
21332
21343
|
this.internalModify(this.editor.value);
|
21333
21344
|
this.editor.on("change", this.handleEditorChange);
|
@@ -21468,6 +21479,24 @@ const _sfc_main = {
|
|
21468
21479
|
ele.children = null;
|
21469
21480
|
}
|
21470
21481
|
},
|
21482
|
+
//针对node转为元素进行额外的处理
|
21483
|
+
handleCustomParseNode(ele) {
|
21484
|
+
if (ele.parsedom == "code") {
|
21485
|
+
ele.parsedom = "span";
|
21486
|
+
const marks = {
|
21487
|
+
"data-editify-code": true
|
21488
|
+
};
|
21489
|
+
if (ele.hasMarks()) {
|
21490
|
+
Object.assign(ele.marks, marks);
|
21491
|
+
} else {
|
21492
|
+
ele.marks = marks;
|
21493
|
+
}
|
21494
|
+
}
|
21495
|
+
if (typeof this.customParseNode == "function") {
|
21496
|
+
ele = this.customParseNode.apply(this, [ele]);
|
21497
|
+
}
|
21498
|
+
return ele;
|
21499
|
+
},
|
21471
21500
|
//隐藏工具条
|
21472
21501
|
hideToolbar() {
|
21473
21502
|
this.toolbarOptions.show = false;
|
@@ -21703,20 +21732,22 @@ const _sfc_main = {
|
|
21703
21732
|
},
|
21704
21733
|
//编辑器粘贴html
|
21705
21734
|
handlePasteHtml(elements, data2) {
|
21735
|
+
const keepStyles = Object.assign(pasteKeepData.styles, this.pasteKeepStyles || {});
|
21736
|
+
const keepMarks = Object.assign(pasteKeepData.marks, this.pasteKeepMarks || {});
|
21706
21737
|
AlexElement.flatElements(elements).forEach((el) => {
|
21707
21738
|
let marks = {};
|
21708
21739
|
let styles = {};
|
21709
21740
|
if (el.hasMarks()) {
|
21710
|
-
for (let key in
|
21711
|
-
if (el.marks.hasOwnProperty(key) && (Array.isArray(
|
21741
|
+
for (let key in keepMarks) {
|
21742
|
+
if (el.marks.hasOwnProperty(key) && (Array.isArray(keepMarks[key]) && keepMarks[key].includes(el.parsedom) || keepMarks[key] == "*")) {
|
21712
21743
|
marks[key] = el.marks[key];
|
21713
21744
|
}
|
21714
21745
|
}
|
21715
21746
|
el.marks = marks;
|
21716
21747
|
}
|
21717
21748
|
if (el.hasStyles() && !el.isText()) {
|
21718
|
-
for (let key in
|
21719
|
-
if (el.styles.hasOwnProperty(key) && (Array.isArray(
|
21749
|
+
for (let key in keepStyles) {
|
21750
|
+
if (el.styles.hasOwnProperty(key) && (Array.isArray(keepStyles[key]) && keepStyles[key].includes(el.parsedom) || keepStyles[key] == "*")) {
|
21720
21751
|
styles[key] = el.styles[key];
|
21721
21752
|
}
|
21722
21753
|
}
|
@@ -22783,7 +22814,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
22783
22814
|
])) : createCommentVNode("", true)
|
22784
22815
|
]);
|
22785
22816
|
}
|
22786
|
-
const Editify = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-
|
22817
|
+
const Editify = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-8415c1dc"]]);
|
22787
22818
|
const iconfont = "";
|
22788
22819
|
const en_US = {
|
22789
22820
|
textWrapUp: "Up feed",
|
@@ -22962,7 +22993,7 @@ const i18n = (locale) => {
|
|
22962
22993
|
return translations[locale][key];
|
22963
22994
|
};
|
22964
22995
|
};
|
22965
|
-
const version = "0.0.
|
22996
|
+
const version = "0.0.36";
|
22966
22997
|
const install = (app, props) => {
|
22967
22998
|
const locale = (props ? props.locale : "zh_CN") || "zh_CN";
|
22968
22999
|
app.provide("$editTrans", i18n(locale));
|