vue-editify 0.0.34 → 0.0.35
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/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 +1 -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.35";
|
22966
22997
|
const install = (app, props) => {
|
22967
22998
|
const locale = (props ? props.locale : "zh_CN") || "zh_CN";
|
22968
22999
|
app.provide("$editTrans", i18n(locale));
|