workflow(sfc-playground): tweaks and commit links
This commit is contained in:
parent
69b4727204
commit
3aaa53748b
@ -1,35 +1,44 @@
|
||||
<template>
|
||||
<nav>
|
||||
<h1>Vue SFC Playground</h1>
|
||||
|
||||
<button class="share" @click="copyLink">
|
||||
<svg width="1.4em" height="1.4em" viewBox="0 0 24 24">
|
||||
<g fill="none" stroke="#626262" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="18" cy="5" r="3"/>
|
||||
<circle cx="6" cy="12" r="3"/>
|
||||
<circle cx="18" cy="19" r="3"/>
|
||||
<path d="M8.59 13.51l6.83 3.98"/>
|
||||
<path d="M15.41 6.51l-6.82 3.98"/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button class="download" @click="downloadProject">
|
||||
<svg width="1.7em" height="1.7em" viewBox="0 0 24 24">
|
||||
<g fill="#626262">
|
||||
<rect x="4" y="18" width="16" height="2" rx="1" ry="1"/>
|
||||
<rect x="3" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 5 18)"/>
|
||||
<rect x="17" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 19 18)"/>
|
||||
<path d="M12 15a1 1 0 0 1-.58-.18l-4-2.82a1 1 0 0 1-.24-1.39a1 1 0 0 1 1.4-.24L12 12.76l3.4-2.56a1 1 0 0 1 1.2 1.6l-4 3a1 1 0 0 1-.6.2z"/><path d="M12 13a1 1 0 0 1-1-1V4a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1z"/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="links">
|
||||
<a class="commit-link" :href="`https://github.com/vuejs/vue-next/tree/${commit}`" target="_blank">
|
||||
vue@{{ commit }}
|
||||
</a>
|
||||
<a class="commit-link" href="https://app.netlify.com/sites/vue-sfc-playground/deploys" target="_blank">
|
||||
History
|
||||
</a>
|
||||
<button class="share" @click="copyLink">
|
||||
<svg width="1.4em" height="1.4em" viewBox="0 0 24 24">
|
||||
<g fill="none" stroke="#626262" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="18" cy="5" r="3"/>
|
||||
<circle cx="6" cy="12" r="3"/>
|
||||
<circle cx="18" cy="19" r="3"/>
|
||||
<path d="M8.59 13.51l6.83 3.98"/>
|
||||
<path d="M15.41 6.51l-6.82 3.98"/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="download" @click="downloadProject">
|
||||
<svg width="1.7em" height="1.7em" viewBox="0 0 24 24">
|
||||
<g fill="#626262">
|
||||
<rect x="4" y="18" width="16" height="2" rx="1" ry="1"/>
|
||||
<rect x="3" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 5 18)"/>
|
||||
<rect x="17" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 19 18)"/>
|
||||
<path d="M12 15a1 1 0 0 1-.58-.18l-4-2.82a1 1 0 0 1-.24-1.39a1 1 0 0 1 1.4-.24L12 12.76l3.4-2.56a1 1 0 0 1 1.2 1.6l-4 3a1 1 0 0 1-.6.2z"/>
|
||||
<path d="M12 13a1 1 0 0 1-1-1V4a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1z"/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { downloadProject } from './download/download'
|
||||
|
||||
const commit = __COMMIT__
|
||||
|
||||
function copyLink() {
|
||||
navigator.clipboard.writeText(location.href)
|
||||
alert('Sharable URL has been copied to clipboard.')
|
||||
@ -45,23 +54,37 @@ nav {
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.33);
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
line-height: var(--nav-height);
|
||||
font-weight: 500;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.commit-link {
|
||||
color: var(--color-branding);
|
||||
text-decoration: none;
|
||||
margin-left: 6px;
|
||||
vertical-align: middle;
|
||||
line-height: var(--nav-height);
|
||||
}
|
||||
|
||||
.share {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 56px;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
}
|
||||
|
||||
.download {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
right: 16px;
|
||||
position: relative;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.commit-link {
|
||||
margin: 0 5px;
|
||||
}
|
||||
</style>
|
||||
|
@ -30,26 +30,22 @@ async function updatePreview() {
|
||||
const modules = compileModulesForPreview()
|
||||
console.log(`successfully compiled ${modules.length} modules.`)
|
||||
// reset modules
|
||||
await proxy.eval(`
|
||||
window.__modules__ = {}
|
||||
window.__css__ = ''
|
||||
`)
|
||||
// evaluate modules
|
||||
for (const mod of modules) {
|
||||
await proxy.eval(mod)
|
||||
}
|
||||
// reboot
|
||||
await proxy.eval(`
|
||||
import { createApp as _createApp } from "${SANDBOX_VUE_URL}"
|
||||
if (window.__app__) {
|
||||
window.__app__.unmount()
|
||||
document.getElementById('app').innerHTML = ''
|
||||
}
|
||||
document.getElementById('__sfc-styles').innerHTML = window.__css__
|
||||
const app = window.__app__ = _createApp(__modules__["${MAIN_FILE}"].default)
|
||||
app.config.errorHandler = e => console.error(e)
|
||||
app.mount('#app')
|
||||
`)
|
||||
await proxy.eval([
|
||||
`window.__modules__ = {};window.__css__ = ''`,
|
||||
...modules,
|
||||
`
|
||||
import { createApp as _createApp } from "${SANDBOX_VUE_URL}"
|
||||
|
||||
if (window.__app__) {
|
||||
window.__app__.unmount()
|
||||
document.getElementById('app').innerHTML = ''
|
||||
}
|
||||
|
||||
document.getElementById('__sfc-styles').innerHTML = window.__css__
|
||||
const app = window.__app__ = _createApp(__modules__["${MAIN_FILE}"].default)
|
||||
app.config.errorHandler = e => console.error(e)
|
||||
app.mount('#app')`.trim()
|
||||
])
|
||||
} catch (e) {
|
||||
runtimeError.value = e.stack
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ export class PreviewProxy {
|
||||
}
|
||||
}
|
||||
|
||||
eval(script: string) {
|
||||
eval(script: string | string[]) {
|
||||
return this.iframe_command('eval', { script })
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
</style>
|
||||
<style id="__sfc-styles"></style>
|
||||
<script type="module">
|
||||
let scriptEl
|
||||
let scriptEls = []
|
||||
|
||||
window.__modules__ = {}
|
||||
|
||||
@ -25,24 +25,41 @@
|
||||
return Promise.resolve(window.__modules__[key])
|
||||
}
|
||||
|
||||
function handle_message(ev) {
|
||||
async function handle_message(ev) {
|
||||
let { action, cmd_id } = ev.data;
|
||||
const send_message = (payload) => parent.postMessage( { ...payload }, ev.origin);
|
||||
const send_reply = (payload) => send_message({ ...payload, cmd_id });
|
||||
const send_ok = window.send_ok = () => send_reply({ action: 'cmd_ok' });
|
||||
const send_ok = () => send_reply({ action: 'cmd_ok' });
|
||||
const send_error = (message, stack) => send_reply({ action: 'cmd_error', message, stack });
|
||||
|
||||
if (action === 'eval') {
|
||||
try {
|
||||
if (scriptEl) {
|
||||
document.head.removeChild(scriptEl)
|
||||
if (scriptEls.length) {
|
||||
scriptEls.forEach(el => {
|
||||
document.head.removeChild(el)
|
||||
})
|
||||
scriptEls.length = 0
|
||||
}
|
||||
scriptEl = document.createElement('script')
|
||||
scriptEl.setAttribute('type', 'module')
|
||||
// send ok in the module script to ensure sequential evaluation
|
||||
// of multiple proxy.eval() calls
|
||||
scriptEl.innerHTML = ev.data.args.script + `\nwindow.send_ok()`
|
||||
document.head.appendChild(scriptEl)
|
||||
|
||||
let { script: scripts } = ev.data.args
|
||||
if (typeof scripts === 'string') scripts = [scripts]
|
||||
|
||||
for (const script of scripts) {
|
||||
const scriptEl = document.createElement('script')
|
||||
scriptEl.setAttribute('type', 'module')
|
||||
// send ok in the module script to ensure sequential evaluation
|
||||
// of multiple proxy.eval() calls
|
||||
const done = new Promise((resolve, reject) => {
|
||||
window.__next__ = resolve
|
||||
scriptEl.onerror = reject
|
||||
})
|
||||
scriptEl.innerHTML = script + `\nwindow.__next__()`
|
||||
document.head.appendChild(scriptEl)
|
||||
scriptEls.push(scriptEl)
|
||||
await done
|
||||
}
|
||||
window.__next__ = undefined
|
||||
send_ok()
|
||||
} catch (e) {
|
||||
send_error(e.message, e.stack);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ let files: Store['files'] = {}
|
||||
|
||||
const savedFiles = location.hash.slice(1)
|
||||
if (savedFiles) {
|
||||
const saved = JSON.parse(decodeURIComponent(savedFiles))
|
||||
const saved = JSON.parse(atob(savedFiles))
|
||||
for (const filename in saved) {
|
||||
files[filename] = new File(filename, saved[filename])
|
||||
}
|
||||
@ -78,7 +78,7 @@ for (const file in store.files) {
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
location.hash = encodeURIComponent(JSON.stringify(exportFiles()))
|
||||
history.replaceState({}, '', '#' + btoa(JSON.stringify(exportFiles())))
|
||||
})
|
||||
|
||||
export function exportFiles() {
|
||||
|
@ -2,9 +2,15 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { defineConfig, Plugin } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import execa from 'execa'
|
||||
|
||||
const commit = execa.sync('git', ['rev-parse', 'HEAD']).stdout.slice(0, 7)
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue(), copyVuePlugin()],
|
||||
define: {
|
||||
__COMMIT__: JSON.stringify(commit)
|
||||
},
|
||||
optimizeDeps: {
|
||||
exclude: ['consolidate']
|
||||
}
|
||||
@ -13,7 +19,7 @@ export default defineConfig({
|
||||
function copyVuePlugin(): Plugin {
|
||||
return {
|
||||
name: 'copy-vue',
|
||||
generateBundle(_opts, bundle) {
|
||||
generateBundle() {
|
||||
const filePath = path.resolve(
|
||||
__dirname,
|
||||
'../vue/dist/vue.runtime.esm-browser.js'
|
||||
|
Loading…
Reference in New Issue
Block a user