@jx3box/jx3box-editor 0.9.0 → 0.9.4
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/assets/css/markdown.less +19 -0
- package/assets/css/module/table.less +1 -1
- package/package.json +3 -1
- package/readme.md +2 -1
- package/service/cms.js +7 -0
- package/src/Markdown.vue +155 -0
- package/src/Upload.vue +9 -7
- package/vue.config.js +22 -10
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.c-markdown-toolbar-item{
|
|
2
|
+
.mr(5px);
|
|
3
|
+
.pointer;
|
|
4
|
+
padding: 2px 5px 3px 5px;
|
|
5
|
+
|
|
6
|
+
&:hover{
|
|
7
|
+
background: #e9e9eb;
|
|
8
|
+
.r(4px);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
.c-markdown-store-item{
|
|
12
|
+
.none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.c-markdown{
|
|
16
|
+
.markdown-body .hljs{
|
|
17
|
+
background-color:#f6f8fa;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
margin: 10px 0;
|
|
8
8
|
overflow-x: auto;
|
|
9
9
|
max-width: 100%;
|
|
10
|
-
display: block;
|
|
11
10
|
border: none;
|
|
12
11
|
|
|
13
12
|
line-height:2.2;
|
|
@@ -42,6 +41,7 @@
|
|
|
42
41
|
@media screen and (max-width: @phone) {
|
|
43
42
|
.c-article{
|
|
44
43
|
table {
|
|
44
|
+
display: block;
|
|
45
45
|
width: 100% !important;
|
|
46
46
|
height: auto !important;
|
|
47
47
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jx3box/jx3box-editor",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "JX3BOX Article & Editor",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
+
"dev": "env DEV_SERVER=true vue-cli-service serve",
|
|
7
8
|
"serve": "vue-cli-service serve",
|
|
8
9
|
"build": "vue-cli-service build",
|
|
9
10
|
"lint": "vue-cli-service lint",
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"@jx3box/jx3box-emotion": "^1.0.10",
|
|
36
37
|
"@jx3box/jx3box-macro": "^1.0.1",
|
|
37
38
|
"@jx3box/jx3box-talent": "^1.1.2",
|
|
39
|
+
"@jx3box/markdown": "0.0.5",
|
|
38
40
|
"@tinymce/tinymce-vue": "^3.2.2",
|
|
39
41
|
"axios": "^0.19.2",
|
|
40
42
|
"core-js": "^3.6.5",
|
package/readme.md
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
$ npm install
|
|
8
8
|
$ npm run serve
|
|
9
9
|
$ open http://localhost:8080 //文章渲染
|
|
10
|
-
$ open http://localhost:8080/tinymce
|
|
10
|
+
$ open http://localhost:8080/tinymce //tinymce编辑器
|
|
11
|
+
$ open http://localhost:8080/markdown //markdown编辑器
|
|
11
12
|
$ tinymce http://localhost:5000
|
|
12
13
|
```
|
|
13
14
|
|
package/service/cms.js
ADDED
package/src/Markdown.vue
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="c-markdown">
|
|
3
|
+
<input class="c-markdown-store-item" id="c-markdown-store-images" type="file" @change="uploadImages" ref="markdownImages" multiple :accept="allow_image_types" />
|
|
4
|
+
<input class="c-markdown-store-item" id="c-markdown-store-files" type="file" @change="uploadFiles" ref="markdownFiles" multiple />
|
|
5
|
+
<mavon-editor class="c-markdown-box" ref="md" v-model="data" :editable="true" :navigation="false">
|
|
6
|
+
<template slot="left-toolbar-after">
|
|
7
|
+
<span class="c-markdown-toolbar-image c-markdown-toolbar-item" title="上传图片" @click="selectImages"><i class="el-icon-picture-outline-round"></i></span>
|
|
8
|
+
<span class="c-markdown-toolbar-file c-markdown-toolbar-item" title="上传附件" @click="selectFiles"><i class="el-icon-paperclip"></i></span>
|
|
9
|
+
</template>
|
|
10
|
+
</mavon-editor>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
import { uploadFile } from "../service/cms";
|
|
16
|
+
export default {
|
|
17
|
+
name: "Markdown",
|
|
18
|
+
props: {
|
|
19
|
+
content: {
|
|
20
|
+
type: String,
|
|
21
|
+
},
|
|
22
|
+
editable: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
components: {},
|
|
28
|
+
data: function() {
|
|
29
|
+
return {
|
|
30
|
+
data: this.content,
|
|
31
|
+
allow_image_types: ["image/png", "image/jpeg", "image/gif", "image/bmp", "image/webp"],
|
|
32
|
+
allow_file_types: [],
|
|
33
|
+
image_ext: ["png", "jpg", "gif", "bmp", "webp"],
|
|
34
|
+
files: [],
|
|
35
|
+
resolved_files: [],
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
model: {
|
|
39
|
+
prop: "content",
|
|
40
|
+
event: "update",
|
|
41
|
+
},
|
|
42
|
+
watch: {
|
|
43
|
+
data: function(newval) {
|
|
44
|
+
this.$emit("update", newval);
|
|
45
|
+
},
|
|
46
|
+
content: function(newval) {
|
|
47
|
+
this.data = newval;
|
|
48
|
+
},
|
|
49
|
+
// 监听过滤后的文件列表
|
|
50
|
+
files_list: function(list) {
|
|
51
|
+
this.bulkUpload(list);
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
computed: {
|
|
55
|
+
// 将fileList类数组转为标准数组
|
|
56
|
+
// images_list: function() {
|
|
57
|
+
// let images = Array.from(this.images);
|
|
58
|
+
// let _images = [];
|
|
59
|
+
// for (let item of images) {
|
|
60
|
+
// if (this.allow_image_types.includes(item.type)) {
|
|
61
|
+
// _images.push(item);
|
|
62
|
+
// }
|
|
63
|
+
// }
|
|
64
|
+
// return _images;
|
|
65
|
+
// },
|
|
66
|
+
files_list: function() {
|
|
67
|
+
let files = Array.from(this.files);
|
|
68
|
+
return files;
|
|
69
|
+
},
|
|
70
|
+
$md : function (){
|
|
71
|
+
return this.$refs.md
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
methods: {
|
|
75
|
+
// 点击上传按钮
|
|
76
|
+
selectImages: function() {
|
|
77
|
+
document.getElementById("c-markdown-store-images").dispatchEvent(new MouseEvent("click"));
|
|
78
|
+
},
|
|
79
|
+
selectFiles: function() {
|
|
80
|
+
document.getElementById("c-markdown-store-files").dispatchEvent(new MouseEvent("click"));
|
|
81
|
+
},
|
|
82
|
+
// 监听选择结果变化
|
|
83
|
+
uploadImages: function(e) {
|
|
84
|
+
this.files = this.$refs.markdownImages.files;
|
|
85
|
+
},
|
|
86
|
+
uploadFiles: function(e) {
|
|
87
|
+
this.files = this.$refs.markdownFiles.files;
|
|
88
|
+
},
|
|
89
|
+
// 批量上传
|
|
90
|
+
bulkUpload: function(list) {
|
|
91
|
+
// 存在有效数据队列时
|
|
92
|
+
if (!list || !list.length) return;
|
|
93
|
+
|
|
94
|
+
// 上传队列
|
|
95
|
+
let queue = [];
|
|
96
|
+
for (let item of list) {
|
|
97
|
+
let formdata = new FormData();
|
|
98
|
+
formdata.append("file", item);
|
|
99
|
+
queue.push(uploadFile(formdata));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 回调处理
|
|
103
|
+
Promise.allSettled(queue)
|
|
104
|
+
.then((results) => {
|
|
105
|
+
results.forEach((result, i) => {
|
|
106
|
+
if (result.status == "fulfilled") {
|
|
107
|
+
let url = result.value.data?.data?.[0];
|
|
108
|
+
this.resolved_files.push({
|
|
109
|
+
url: url,
|
|
110
|
+
filename: list[i]["name"],
|
|
111
|
+
type : list[i]['type'],
|
|
112
|
+
ext : list[i]["name"].split('.').pop()
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
this.insertFiles()
|
|
117
|
+
})
|
|
118
|
+
.finally(() => {
|
|
119
|
+
// 上传完成后清空input
|
|
120
|
+
this.images = [];
|
|
121
|
+
this.files = [];
|
|
122
|
+
this.resolved_files = [];
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
// 插入正文
|
|
126
|
+
insertFiles : function (){
|
|
127
|
+
for(let item of this.resolved_files){
|
|
128
|
+
// 插入图片
|
|
129
|
+
if(this.image_ext.includes(item.ext)){
|
|
130
|
+
this.$md.insertText(this.$md.getTextareaDom(), {
|
|
131
|
+
prefix: ``,
|
|
132
|
+
subfix: "",
|
|
133
|
+
str: "",
|
|
134
|
+
});
|
|
135
|
+
// 插入文字链接
|
|
136
|
+
}else{
|
|
137
|
+
this.$md.insertText(this.$md.getTextareaDom(), {
|
|
138
|
+
prefix: `[${item.filename}](${item.url})`,
|
|
139
|
+
subfix: "",
|
|
140
|
+
str: "",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
},
|
|
147
|
+
filters: {},
|
|
148
|
+
created: function() {},
|
|
149
|
+
mounted: function() {},
|
|
150
|
+
};
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
<style lang="less">
|
|
154
|
+
@import "../assets/css/markdown.less";
|
|
155
|
+
</style>
|
package/src/Upload.vue
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
:file-list="fileList"
|
|
29
29
|
:on-change="change"
|
|
30
30
|
ref="uploadbox"
|
|
31
|
+
:accept="accept"
|
|
31
32
|
>
|
|
32
33
|
<!-- :accept="accept" -->
|
|
33
34
|
<i slot="default" class="el-icon-plus"></i>
|
|
@@ -86,13 +87,12 @@ const imgtypes = ["jpg", "png", "gif", "bmp", "webp"];
|
|
|
86
87
|
|
|
87
88
|
export default {
|
|
88
89
|
name: "Upload",
|
|
89
|
-
props: ["text"],
|
|
90
|
+
props: ["text",'onlyImage','desc','accept'],
|
|
90
91
|
data: function () {
|
|
91
92
|
return {
|
|
92
93
|
API: API,
|
|
93
94
|
dialogVisible: false,
|
|
94
|
-
tip:
|
|
95
|
-
"一次最多同时上传10个文件(不超过5M),格式限常见的图片、文档、数据表及压缩包",
|
|
95
|
+
tip: this.desc || "一次最多同时上传10个文件(不超过5M),格式限常见的图片、文档、数据表及压缩包",
|
|
96
96
|
btn_txt: this.text || "上传附件",
|
|
97
97
|
|
|
98
98
|
fileList: [],
|
|
@@ -129,6 +129,12 @@ export default {
|
|
|
129
129
|
// return;
|
|
130
130
|
// }
|
|
131
131
|
|
|
132
|
+
// 分析文件类型
|
|
133
|
+
let ext = file.name.split(".").pop();
|
|
134
|
+
let is_img = imgtypes.includes(ext);
|
|
135
|
+
|
|
136
|
+
if(this.onlyImage && !is_img) return
|
|
137
|
+
|
|
132
138
|
// 构建数据
|
|
133
139
|
let fdata = new FormData();
|
|
134
140
|
fdata.append("file", file.raw);
|
|
@@ -149,10 +155,6 @@ export default {
|
|
|
149
155
|
// 修改path
|
|
150
156
|
file.url = res.data.data && res.data.data[0];
|
|
151
157
|
|
|
152
|
-
// 分析文件类型
|
|
153
|
-
let ext = file.name.split(".").pop();
|
|
154
|
-
let is_img = imgtypes.includes(ext);
|
|
155
|
-
|
|
156
158
|
// 额外赋值
|
|
157
159
|
file.is_img = is_img;
|
|
158
160
|
file.selected = true;
|
package/vue.config.js
CHANGED
|
@@ -18,6 +18,12 @@ module.exports = {
|
|
|
18
18
|
template : 'public/tinymce.html',
|
|
19
19
|
filename:'tinymce/index.html',
|
|
20
20
|
},
|
|
21
|
+
markdown : {
|
|
22
|
+
title : 'Markdown编辑器',
|
|
23
|
+
entry:'demo/M.js',
|
|
24
|
+
template : 'public/article.html',
|
|
25
|
+
filename:'markdown/index.html',
|
|
26
|
+
},
|
|
21
27
|
},
|
|
22
28
|
|
|
23
29
|
|
|
@@ -48,16 +54,22 @@ module.exports = {
|
|
|
48
54
|
'/',
|
|
49
55
|
|
|
50
56
|
//❤️ Porxy ~
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
devServer: {
|
|
58
|
+
proxy: {
|
|
59
|
+
"/api/cms": {
|
|
60
|
+
"target": process.env["DEV_SERVER"] == "true" ? "http://localhost:5120" : "https://cms.jx3box.com",
|
|
61
|
+
"onProxyReq": function (request) {
|
|
62
|
+
request.setHeader("origin", "");
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"/api": {
|
|
66
|
+
"target": process.env["DEV_SERVER"] == "true" ? "http://localhost:51818" : "https://next.jx3box.com",
|
|
67
|
+
"onProxyReq": function (request) {
|
|
68
|
+
request.setHeader("origin", "");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
61
73
|
|
|
62
74
|
chainWebpack: config => {
|
|
63
75
|
|