Skip to content

Commit fbac556

Browse files
author
shangbin
committed
feat: 支持输出Vue2以及Vue3代码
1 parent 45e13cd commit fbac556

File tree

4 files changed

+148
-43
lines changed

4 files changed

+148
-43
lines changed

package-lock.json

Lines changed: 46 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"crypto-random-string": "^3.3.1",
3333
"css": "^3.0.0",
3434
"css-scoped": "^1.0.0",
35+
"ejs": "^3.1.6",
3536
"element-plus": "^1.2.0-beta.3",
3637
"escodegen": "^2.0.0",
3738
"espree": "^7.3.0",

src/components/Code.vue

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,29 @@
66
<div style="color: #666; font-size: 12px; text-align:center; margin: 5px;">使用代码前请确认相应的组件库已集成至项目</div>
77
<div style="text-align:left;">
88
<el-row>
9-
<el-col :span="6">
9+
<el-col :span="5">
1010
输出形式:
1111
<el-radio-group v-model="outputMode" style="display: flex; flex-direction: column;">
1212
<el-radio label="vue">Vue</el-radio>
1313
<el-radio label="html">单页Html</el-radio>
1414
</el-radio-group>
1515
</el-col>
1616

17-
<el-col :span="6" v-if="outputMode === 'html'">
17+
<el-col :span="5" v-if="outputMode === 'html'">
1818
选择所使用的组件库:
1919
<el-checkbox-group v-model="checkList" style="display: flex; flex-direction: column;">
2020
<el-checkbox label="ele">Element UI</el-checkbox>
2121
<el-checkbox label="antd">Ant Design</el-checkbox>
2222
<el-checkbox label="vant">Vant</el-checkbox>
2323
</el-checkbox-group>
2424
</el-col>
25+
<el-col :span="4" v-if="outputMode === 'html'">
26+
选择Vue版本:
27+
<el-radio-group v-model="vueVersion" style="display: flex; flex-direction: column;">
28+
<el-radio label="2">Vue 2</el-radio>
29+
<el-radio label="3">Vue 3</el-radio>
30+
</el-radio-group>
31+
</el-col>
2532
<el-col :span="10" style="display: flex; flex-direction: column;">
2633
代码获取方式:
2734
<div style="margin-top: 10px;">
@@ -33,7 +40,8 @@
3340
</el-tooltip>
3441
</div>
3542
<div style="margin-top: 10px;" v-if="outputMode === 'html'">
36-
<el-input v-model="fileName" placeholder="部署文件名" style="width: 150px; margin-right: 10px;" size="small"></el-input>
43+
<el-input v-model="fileName" placeholder="部署文件名" style="width: 150px; margin-right: 10px;" size="small">
44+
</el-input>
3745
<el-button size="small" type="danger" :loading="loading" @click="release">
3846
一键部署至VCC静态页面托管服务</el-button>
3947
<div v-if="accessUrl">部署成功:<a :href="accessUrl" target="_blank">{{accessUrl}}</a></div>
@@ -71,7 +79,8 @@ export default {
7179
loading: false,
7280
accessUrl: '',
7381
fileName: '',
74-
checkList: ['ele']
82+
checkList: ['ele'],
83+
vueVersion: '3'
7584
};
7685
},
7786
beforeCreate() { },
@@ -150,7 +159,7 @@ export default {
150159
},
151160
152161
singleIndex() {
153-
const htmlCode = singleIndexOutput(this.rawCode);
162+
const htmlCode = singleIndexOutput(this.rawCode, this.checkList, this.vueVersion === '3');
154163
try {
155164
return prettier.format(htmlCode, {
156165
parser: "html",

src/libs/singleIndexOutput.js

Lines changed: 87 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,105 @@
1-
import { parseComponent } from 'vue-template-compiler/browser';
1+
import { parseComponent } from "vue-template-compiler/browser";
2+
import ejs from "ejs";
23

3-
const outputVue2Template = `<!DOCTYPE html>
4+
const outputVueTemplate = `
5+
<!DOCTYPE html>
46
<html>
57
<head>
68
<meta charset="UTF-8">
7-
<title>VCC预览</title>
8-
<!-- import CSS -->
9-
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
10-
<style stype="text/css">#styleTemplate</style>
9+
<title>页面预览</title>
10+
<style stype="text/css">
11+
<%= style %>
12+
</style>
13+
<% for(var i = 0; i < cssLibs.length; ++i) { %>
14+
<link href="<%= cssLibs[i] %>" rel="stylesheet"><% } %>
1115
</head>
1216
<body>
1317
<div id="app">
14-
#templateHolder
18+
<%- templateHolder %>
1519
</div>
1620
</body>
17-
<!-- import Vue before Element -->
18-
<script src="https://unpkg.com/vue/dist/vue.js"></script>
19-
<!-- import JavaScript -->
20-
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
21-
<script>
22-
new Vue(#logicHolder).$mount("#app");
23-
</script>
24-
</html>`
25-
26-
export default function (vueCode) {
21+
<% for(var i = 0; i < scriptLibs.length; ++i) { %>
22+
<script src="<%= scriptLibs[i] %>"></script><% } %>
23+
<script>
24+
25+
<% if(vue3) {%>Vue.createApp(<%-logicHolder%>)<% for(var i = 0; i < vue3UseLib.length; ++i) { %>
26+
.use(<%= vue3UseLib[i] %>)<%}%>
27+
.mount("#app"); %>
28+
<% } else {%>new Vue(<%- logicHolder %>).$mount("#app")<%}%>
29+
</script>
30+
</html>`;
31+
32+
const libAddressMap = {
33+
vue: {
34+
js: ["https://cdn.bootcdn.net/ajax/libs/vue/3.2.31/vue.global.min.js"],
35+
css: "",
36+
},
37+
ele: {
38+
js: ["https://cdn.bootcdn.net/ajax/libs/element-plus/2.1.0/index.full.min.js"],
39+
css: "https://cdn.bootcdn.net/ajax/libs/element-plus/2.1.0/theme-chalk/index.min.css",
40+
libName: "ElementPlus",
41+
},
42+
antd: {
43+
js: [
44+
"https://cdn.bootcdn.net/ajax/libs/dayjs/1.10.8/dayjs.min.js",
45+
"https://cdn.bootcdn.net/ajax/libs/ant-design-vue/3.0.0-alpha.14/antd.min.js",
46+
],
47+
css: "https://cdn.bootcdn.net/ajax/libs/ant-design-vue/3.0.0-alpha.14/antd.min.css",
48+
libName: "antd",
49+
},
50+
vant: {
51+
js: ["https://cdn.bootcdn.net/ajax/libs/vant/3.3.7/vant.min.js"],
52+
css: "https://cdn.bootcdn.net/ajax/libs/vant/3.3.7/index.min.css",
53+
libName: "vant",
54+
},
55+
};
56+
57+
export default function (vueCode, dependenciesLibs, vue3 = true) {
2758
const { template, script, styles, customBlocks } = parseComponent(vueCode);
2859

2960
let newScript = script.content.replace(/\s*export default\s*/, "");
3061

31-
let output = outputVue2Template;
62+
const tempDependenciesLibs = dependenciesLibs.slice();
63+
const tempLibAddressMap = vue3 ? libAddressMap: libAddressMapForVue2
64+
65+
tempDependenciesLibs.unshift("vue");
3266

33-
output = output.replace("#templateHolder", template.content);
34-
output = output.replace("#logicHolder", newScript);
35-
output = output.replace("#styleTemplate", styles[0].content);
67+
const output = ejs.render(outputVueTemplate, {
68+
cssLibs: tempDependenciesLibs.map((item) => tempLibAddressMap[item].css).filter((item) => !!item),
69+
scriptLibs: tempDependenciesLibs
70+
.map((item) => tempLibAddressMap[item].js)
71+
.flat()
72+
.filter((item) => !!item),
73+
vue3,
74+
vue3UseLib: tempDependenciesLibs
75+
.filter((item) => item != "vue")
76+
.map((item) => tempLibAddressMap[item].libName),
77+
style: styles[0].content,
78+
templateHolder: template.content,
79+
logicHolder: newScript,
80+
});
3681

3782
return output;
3883
}
3984

85+
const libAddressMapForVue2 = {
86+
vue: {
87+
js: ["https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"],
88+
css: "",
89+
},
90+
ele: {
91+
js: ["https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.7/index.min.js"],
92+
css: "https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.7/theme-chalk/index.min.css",
93+
},
94+
antd: {
95+
js: [
96+
"https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/moment.min.js",
97+
"https://cdn.bootcdn.net/ajax/libs/ant-design-vue/1.7.8/antd.js",
98+
],
99+
css: "https://cdn.bootcdn.net/ajax/libs/ant-design-vue/1.7.8/antd.css",
100+
},
101+
vant: {
102+
js: ["https://cdn.bootcdn.net/ajax/libs/vant/2.12.44/vant.min.js"],
103+
css: "https://cdn.bootcdn.net/ajax/libs/vant/2.12.44/index.min.css",
104+
},
105+
};

0 commit comments

Comments
 (0)