修复plyaground的bug

master
yutent 2023-04-27 11:34:24 +08:00
parent 2790776723
commit e3df7f6eee
3 changed files with 84 additions and 65 deletions

View File

@ -21,13 +21,15 @@ export default {
watch: { watch: {
code(v) { code(v) {
let doc = this.$view.state.doc let doc = this.$view.state.doc
let { anchor } = this.$view.state.selection.main
this.$view.dispatch({ this.$view.dispatch({
changes: { changes: {
from: 0, from: 0,
to: doc.length, to: doc.length,
insert: v insert: v
} },
selection: { anchor } //
}) })
} }
}, },
@ -49,12 +51,12 @@ export default {
EditorView.lineWrapping, EditorView.lineWrapping,
// //
EditorView.updateListener.of(v => { EditorView.updateListener.of(v => {
let value = v.state.doc.toString().trim() let value = v.state.doc.toString()
if (!this.$last || value === this.$last) { if (!this.$last || value.trim() === this.$last) {
this.$last = value this.$last = value.trim()
return return
} }
this.$last = value this.$last = value.trim()
this.$emit('change', value, lang) this.$emit('change', value, lang)
}) })
), ),
@ -75,5 +77,6 @@ export default {
.cm-editor { .cm-editor {
width: 100%; width: 100%;
height: 100%; height: 100%;
outline: none !important;
} }
</style> </style>

View File

@ -12,7 +12,7 @@
<CodeEditor lang="css" :code="css" @change="updateCode" /> <CodeEditor lang="css" :code="css" @change="updateCode" />
</wc-tab> </wc-tab>
</wc-tabs> </wc-tabs>
<Preview :code="preview" /> <Preview ref="preview" />
</div> </div>
</template> </template>
@ -23,35 +23,6 @@ import Preview from './views/preview.vue'
import { gzip, ungzip } from '@bytedo/gzip' import { gzip, ungzip } from '@bytedo/gzip'
const template = `<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<link rel="stylesheet" href="//jscdn.ink/@bd/ui/latest/css/reset-basic.css">
{{css}}
<script async src="//jscdn.ink/es-module-shims/1.6.3/es-module-shims.wasm.js"><\/script>
<script type="importmap">${JSON.stringify({
imports: {
vue: '//jscdn.ink/vue/3.2.47/vue.runtime.esm-browser.prod.js',
'vue-router': '//jscdn.ink/@bytedo/vue-router/4.1.6/vue-router.js',
fetch: '//jscdn.ink/@bytedo/fetch/latest/next.js',
'@bytedo/editor': '//jscdn.ink/@bytedo/editor/latest/index.js',
'@bytedo/gzip': '//jscdn.ink/@bytedo/gzip/latest/index.js',
'@bd/core': '//jscdn.ink/@bd/core/latest/index.js'
}
})}<\/script>
<script type="module">
{{js}}
<\/script>
</head>
<body>
{{html}}
<\/body>
<\/html>
`
export default { export default {
components: { Topbar, CodeEditor, Preview }, components: { Topbar, CodeEditor, Preview },
data() { data() {
@ -93,22 +64,21 @@ export default {
}, },
updateCode(code, lang) { updateCode(code, lang) {
let { html, js, css } = this
let codez
this[lang] = code this[lang] = code
this.updatePreview(true)
codez = gzip(JSON.stringify({ html, js, css, [lang]: code }))
this.$needUpdate = false
location.hash = codez
this.$refs.preview.render({ [lang]: code })
}, },
updatePreview(sync) { updatePreview(sync) {
let { html, js, css } = this let { html, js, css } = this
if (sync) { this.$refs.preview.render({ html, js, css })
let code = gzip(JSON.stringify({ html, js, css }))
this.$needUpdate = false
location.hash = code
}
this.preview = template
.replace('{{css}}', css)
.replace('{{html}}', html)
.replace('{{js}}', js)
} }
} }
} }

View File

@ -3,31 +3,56 @@
<div class="loading"> <div class="loading">
<span class="thumb" :style="{ width: progress + '%' }"></span> <span class="thumb" :style="{ width: progress + '%' }"></span>
</div> </div>
<iframe class="web" ref="preview"></iframe> <iframe class="web" ref="view"></iframe>
</main> </main>
</template> </template>
<script> <script>
import { nextTick } from 'vue' import { nextTick } from 'vue'
const template = `<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<link rel="stylesheet" href="//jscdn.ink/@bd/ui/latest/css/reset-basic.css">
<style name="css"></style>
<script async src="//jscdn.ink/es-module-shims/1.6.3/es-module-shims.wasm.js"><\/script>
<script type="importmap">${JSON.stringify({
imports: {
vue: '//jscdn.ink/vue/3.2.47/vue.runtime.esm-browser.prod.js',
'vue-router': '//jscdn.ink/@bytedo/vue-router/4.1.6/vue-router.js',
fetch: '//jscdn.ink/@bytedo/fetch/latest/next.js',
'@bytedo/editor': '//jscdn.ink/@bytedo/editor/latest/index.js',
'@bytedo/gzip': '//jscdn.ink/@bytedo/gzip/latest/index.js',
'@bd/core': '//jscdn.ink/@bd/core/latest/index.js'
}
})}<\/script>
</head>
<body><\/body>
<\/html>
`
let startTime = 0 let startTime = 0
let pending = false
export default { export default {
props: {
code: ''
},
data() { data() {
return { return {
progress: 0 progress: 0
} }
}, },
watch: { mounted() {
code(v) { this.$code = {}
// console.log(v)
this.updatePreview(v) try {
} let doc = this.$refs.view.contentDocument
doc.open()
doc.write(template)
doc.close()
} catch (e) {}
}, },
methods: { methods: {
@ -39,26 +64,47 @@ export default {
let _time = stamp - startTime let _time = stamp - startTime
// _time / 2000 * 100 % // _time / 2000 * 100 %
this.progress = ~~(_time / 20) this.progress = ~~(_time / 10)
if (_time > 2000) { if (pending && _time > 1000) {
this.progress = 0 this.progress = 0
let doc = this.$refs.preview.contentDocument let doc = this.$refs.view.contentDocument
for (let k in this.$code) {
switch (k) {
case 'html':
doc.body.innerHTML = this.$code[k]
break
case 'js':
if (doc.head.children.namedItem('js')) {
doc.head.children.namedItem('js').textContent = this.$code[k]
} else {
let script = document.createElement('script')
script.name = 'js'
script.type = 'module'
script.textContent = this.$code[k]
doc.head.append(script)
}
break
case 'css':
doc.head.children.namedItem('css').textContent = this.$code[k]
break
}
}
pending = false
try {
doc.open()
doc.write(this.code)
doc.close()
} catch (e) {}
return return
} }
requestAnimationFrame(this.loading) requestAnimationFrame(this.loading)
}, },
updatePreview(html) { render(code = {}) {
startTime = 0 startTime = 0
pending = true
this.progress = 0 this.progress = 0
this.$code = code
requestAnimationFrame(this.loading) requestAnimationFrame(this.loading)
} }