完善playground
parent
22aecaf220
commit
2790776723
|
@ -15,24 +15,62 @@ import {
|
|||
export default {
|
||||
props: {
|
||||
lang: { type: String, default: 'vue' },
|
||||
code: String
|
||||
code: ''
|
||||
},
|
||||
|
||||
watch: {
|
||||
code(v) {
|
||||
let doc = this.$view.state.doc
|
||||
|
||||
this.$view.dispatch({
|
||||
changes: {
|
||||
from: 0,
|
||||
to: doc.length,
|
||||
insert: v
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
let lang = this.lang
|
||||
this.$last = this.code
|
||||
|
||||
this.$view = new EditorView({
|
||||
doc: this.code,
|
||||
extensions: minimalSetup(vue(), EditorView.lineWrapping),
|
||||
extensions: minimalSetup(
|
||||
lang === 'html'
|
||||
? html()
|
||||
: lang === 'js'
|
||||
? javascript()
|
||||
: lang === 'css'
|
||||
? css()
|
||||
: vue(),
|
||||
EditorView.lineWrapping,
|
||||
// 监听代码变化
|
||||
EditorView.updateListener.of(v => {
|
||||
let value = v.state.doc.toString().trim()
|
||||
if (!this.$last || value === this.$last) {
|
||||
this.$last = value
|
||||
return
|
||||
}
|
||||
this.$last = value
|
||||
this.$emit('change', value, lang)
|
||||
})
|
||||
),
|
||||
parent: this.$refs.container
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
width: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
border-right: 1px solid var(--color-plain-2);
|
||||
}
|
||||
.cm-editor {
|
||||
width: 100%;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<nav class="menu">
|
||||
<a :class="{ active: nav === 'index' }" href="./index.html">主页</a>
|
||||
<a :class="{ active: nav === 'docs' }" href="./docs.html">文档</a>
|
||||
<a href="/playground.html">试一试</a>
|
||||
<a target="_blank" href="https://github.com/bd-js/wcui"
|
||||
><img class="github" src="/assets/github.svg" alt="Web Components"
|
||||
/></a>
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
<template>
|
||||
<Topbar />
|
||||
<div class="playground">
|
||||
<CodeEditor :code="code" />
|
||||
<Preview />
|
||||
<wc-tabs class="editor">
|
||||
<wc-tab label="html" name="html">
|
||||
<CodeEditor lang="html" :code="html" @change="updateCode" />
|
||||
</wc-tab>
|
||||
<wc-tab label="javascript" name="js">
|
||||
<CodeEditor lang="js" :code="js" @change="updateCode" />
|
||||
</wc-tab>
|
||||
<wc-tab label="css" name="css">
|
||||
<CodeEditor lang="css" :code="css" @change="updateCode" />
|
||||
</wc-tab>
|
||||
</wc-tabs>
|
||||
<Preview :code="preview" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -11,36 +21,105 @@ import CodeEditor from '@/components/code-editor.vue'
|
|||
import Topbar from './views/topbar.vue'
|
||||
import Preview from './views/preview.vue'
|
||||
|
||||
export default {
|
||||
components: { Topbar, CodeEditor, Preview },
|
||||
data() {
|
||||
return {
|
||||
code: `<!doctype html>
|
||||
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">
|
||||
<title>{{title}}</title>
|
||||
<meta name="keywords" content="{{keywords}}">
|
||||
<meta name="description" content="{{description}}">
|
||||
<link rel="stylesheet" href="//jscdn.ink/@bytedo/wcui/1.0.12/css/reset-basic.css">
|
||||
<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">{{importmap}}<\/script>
|
||||
<\/head>
|
||||
<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>
|
||||
<div class="app noselect"></div>
|
||||
<script src="main.js"><\/script>
|
||||
{{html}}
|
||||
<\/body>
|
||||
<\/html>
|
||||
`
|
||||
|
||||
export default {
|
||||
components: { Topbar, CodeEditor, Preview },
|
||||
data() {
|
||||
return {
|
||||
html: '',
|
||||
js: '',
|
||||
css: '',
|
||||
preview: ''
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
//
|
||||
this.$needUpdate = true
|
||||
|
||||
window.addEventListener('hashchange', ev => {
|
||||
this.handleHashChange()
|
||||
})
|
||||
this.handleHashChange()
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleHashChange() {
|
||||
if (this.$needUpdate) {
|
||||
let code = location.hash.slice(1)
|
||||
if (code) {
|
||||
try {
|
||||
code = ungzip(code)
|
||||
code = JSON.parse(code)
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
this.html = code.html
|
||||
this.js = code.js
|
||||
this.css = code.css
|
||||
this.updatePreview()
|
||||
}
|
||||
this.$needUpdate = true
|
||||
},
|
||||
|
||||
updateCode(code, lang) {
|
||||
this[lang] = code
|
||||
this.updatePreview(true)
|
||||
},
|
||||
updatePreview(sync) {
|
||||
let { html, js, css } = this
|
||||
|
||||
if (sync) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.app {
|
||||
body {
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
}
|
||||
#app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
|
@ -48,7 +127,12 @@ export default {
|
|||
}
|
||||
|
||||
.playground {
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
height: calc(100vh - 48px);
|
||||
}
|
||||
|
||||
.editor {
|
||||
width: 50%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
/**
|
||||
* {}
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @date 2023/04/26 18:28:13
|
||||
*/
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import '//jscdn.ink/@bd/ui/latest/tabs/index.js'
|
||||
|
||||
import App from './app.vue'
|
||||
|
||||
import store from './store'
|
||||
|
|
|
@ -1,12 +1,66 @@
|
|||
<template>
|
||||
<main class="preview"></main>
|
||||
<main class="preview">
|
||||
<div class="loading">
|
||||
<span class="thumb" :style="{ width: progress + '%' }"></span>
|
||||
</div>
|
||||
<iframe class="web" ref="preview"></iframe>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
let startTime = 0
|
||||
|
||||
export default {
|
||||
props: {
|
||||
code: ''
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
content: '欢迎访问~~ 这是首页'
|
||||
progress: 0
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
code(v) {
|
||||
// console.log(v)
|
||||
this.updatePreview(v)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
loading(stamp) {
|
||||
if (startTime === 0) {
|
||||
startTime = stamp
|
||||
}
|
||||
|
||||
let _time = stamp - startTime
|
||||
|
||||
// _time / 2000 * 100 %
|
||||
this.progress = ~~(_time / 20)
|
||||
|
||||
if (_time > 2000) {
|
||||
this.progress = 0
|
||||
let doc = this.$refs.preview.contentDocument
|
||||
|
||||
try {
|
||||
doc.open()
|
||||
doc.write(this.code)
|
||||
doc.close()
|
||||
} catch (e) {}
|
||||
return
|
||||
}
|
||||
|
||||
requestAnimationFrame(this.loading)
|
||||
},
|
||||
|
||||
updatePreview(html) {
|
||||
startTime = 0
|
||||
this.progress = 0
|
||||
|
||||
requestAnimationFrame(this.loading)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +68,42 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.preview {
|
||||
width: 50%;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 50%;
|
||||
border-left: 1px solid var(--color-plain-2);
|
||||
}
|
||||
.web {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
|
||||
.thumb {
|
||||
width: 0;
|
||||
height: 1px;
|
||||
background: var(--color-blue-1);
|
||||
box-shadow: 0 0 5px var(--color-blue-1);
|
||||
|
||||
&.loading {
|
||||
animation: loading 3s linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading {
|
||||
from {
|
||||
width: 0%;
|
||||
}
|
||||
to {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
<template>
|
||||
<header class="topbar noselect">
|
||||
<a class="logo">@bd/ui playground</a>
|
||||
<a class="logo">@bd.js playground</a>
|
||||
|
||||
<a class="github" href="//github.com/bd-js/wcui" target="_blank">github</a>
|
||||
<span class="group">
|
||||
<a class="link" href="/@wcui/index.html">返回首页</a>
|
||||
<a class="link" href="//github.com/bd-js" target="_blank">
|
||||
<img class="github" src="/assets/github.svg" alt="Web Components" />
|
||||
</a>
|
||||
</span>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
|
@ -32,7 +37,18 @@ export default {
|
|||
color: var(--color-red-2);
|
||||
}
|
||||
|
||||
.github {
|
||||
.group {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.link {
|
||||
display: inline-flex;
|
||||
margin-left: 16px;
|
||||
color: var(--color-dark-1);
|
||||
img {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue