Skip to content

Commit 90e1198

Browse files
committed
feat: support & add vue-sfc - *.vue demo
1 parent 1379764 commit 90e1198

File tree

5 files changed

+97
-2
lines changed

5 files changed

+97
-2
lines changed

public/code/index.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
- vue-sfc.vue
12
- moon-star-single-div.js
23
- vue-3d-model.js
34
- turtle.py

public/code/vue-sfc.vue

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<template>
2+
<div class="container">
3+
<h1>Vue Single-file Component</h1>
4+
<h3>Hello. {{message}} {{count}}</h3>
5+
<button @click="add()">Add</button>
6+
</div>
7+
</template>
8+
9+
<script>
10+
module.exports = {
11+
data() {
12+
return { count: 0, message: 'This is Vue App.' };
13+
},
14+
mounted() {
15+
this.timerId = setInterval(this.add, 1000);
16+
},
17+
beforeDestroy() {
18+
let { timerId } = this;
19+
if (timerId) clearInterval(timerId);
20+
},
21+
methods: {
22+
add() {
23+
this.count++;
24+
},
25+
},
26+
};
27+
</script>
28+
29+
<style>
30+
.container {
31+
padding: 20px;
32+
}
33+
</style>

public/code/vue-sfc.vue.png

27.1 KB
Loading

src/playground/codeTransform.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { babelTransform } from './babelMaster';
22

33
export let codeTransform = async (code: string, file: string) => {
44
let isPy = file.endsWith('.py');
5+
let isVue = file.endsWith('.vue');
56
if (isPy) return wrapPy(code);
7+
if (isVue) return wrapVue(code);
68

79
code = wrapJs(code);
810
let hasJsx = file && ['.jsx', '.tsx'].some(ext => file.endsWith(ext));
@@ -11,6 +13,64 @@ export let codeTransform = async (code: string, file: string) => {
1113
return code;
1214
};
1315

16+
export let wrapVue = (code: string) => {
17+
// todo move into rendering
18+
let sandbox = document.createElement('div');
19+
sandbox.innerHTML = code; // safe, script won't be executed
20+
21+
let vueTemplateEl = sandbox.querySelector('template');
22+
let vueTemplate = vueTemplateEl ? vueTemplateEl.innerHTML : '';
23+
let vueScript = '';
24+
sandbox.querySelectorAll('script').forEach(el => {
25+
vueScript += el.innerHTML + '\n\n;;';
26+
});
27+
let vueStyle = '';
28+
sandbox.querySelectorAll('style').forEach(el => {
29+
vueStyle += el.innerHTML + '\n\n';
30+
});
31+
32+
return `
33+
(async () => {
34+
setRendering(true)
35+
36+
let a0 = assetsNode
37+
a0.id = 'assetsNodeOutdated'
38+
let a1 = document.createElement('div')
39+
a1.id = 'assetsNode'
40+
a0.parentNode.appendChild(a1)
41+
42+
ReactDOM.unmountComponentAtNode(mountNode)
43+
mountNode.innerHTML = '' // put behind, otherwise can cause error in react
44+
45+
try {
46+
await loadJs('https://unpkg.com/[email protected]/dist/vue.min.js')
47+
appendCss(${JSON.stringify(vueStyle)})
48+
49+
let module = { exports: null }
50+
;(() => {
51+
;;${vueScript};;
52+
})()
53+
let App = module.exports
54+
App.template = ${JSON.stringify(vueTemplate)}
55+
56+
if (!mountNode.children[0]) {
57+
let innerNode = document.createElement('div')
58+
mountNode.appendChild(innerNode)
59+
}
60+
let curr = mountNode.children[0]
61+
new Vue(App).$mount(curr)
62+
63+
a0.parentNode.removeChild(a0)
64+
} catch (err) {
65+
console.error(['displayError', err])
66+
displayError(err)
67+
} finally {
68+
setRendering(false)
69+
}
70+
})()
71+
`.trim();
72+
};
73+
1474
export let wrapPy = (code: string) => {
1575
return `
1676
(async () => {
@@ -22,8 +82,8 @@ export let wrapPy = (code: string) => {
2282
a1.id = 'assetsNode'
2383
a0.parentNode.appendChild(a1)
2484
25-
// mountNode.innerHTML = '' // can cause error in react
2685
ReactDOM.unmountComponentAtNode(mountNode)
86+
mountNode.innerHTML = '' // put behind, otherwise can cause error in react
2787
2888
try {
2989
// await loadJs('http://www.skulpt.org/js/skulpt.min.js')
@@ -91,7 +151,7 @@ export let wrapJs = (code: string) => {
91151
a0.parentNode.appendChild(a1)
92152
93153
ReactDOM.unmountComponentAtNode(mountNode)
94-
mountNode.innerHTML = '' // put after, otherwise can cause error in react
154+
mountNode.innerHTML = '' // put behind, otherwise can cause error in react
95155
96156
try {
97157
let { useRef, useMemo, useState, useEffect, useLayoutEffect, useReducer, useContext, useCallback, useImperativeHandle } = React

src/playground/util.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export let loadCss = (url: string | string[]): Promise<void> => {
7575
});
7676
};
7777

78+
// todo error-handling
7879
export let appendJs = (code: string) => {
7980
let el = document.createElement('script');
8081
el.innerHTML = code;

0 commit comments

Comments
 (0)