]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
workflow(sfc-playground): tweaks and commit links
authorEvan You <yyx990803@gmail.com>
Mon, 29 Mar 2021 06:07:04 +0000 (02:07 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 29 Mar 2021 06:07:04 +0000 (02:07 -0400)
packages/sfc-playground/src/Header.vue
packages/sfc-playground/src/output/Preview.vue
packages/sfc-playground/src/output/PreviewProxy.ts
packages/sfc-playground/src/output/srcdoc.html
packages/sfc-playground/src/store.ts
packages/sfc-playground/vite.config.ts

index 7d0d501cc2189a91c21f45a34275733ca03bf536..9ba1dbb63f617e48d6c943577e7c62beaa319dcb 100644 (file)
@@ -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>
index ef76c23f3112cfa1492c85d00e83cb1e49537462..0c3feac2fdc8b0f9e2003f027587ee1380537618 100644 (file)
@@ -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
   }
index 338da5ab8681173c8dcfceed5980522d5280ab7f..8c115e0d2ab44a1a8a328c594668875c5367a0b6 100644 (file)
@@ -86,7 +86,7 @@ export class PreviewProxy {
     }
   }
 
-  eval(script: string) {
+  eval(script: string | string[]) {
     return this.iframe_command('eval', { script })
   }
 
index e389e39aa3f3a3c20c9c4f070916e533a7d19364..4446c493247b4db2ab699caf35abb66b2055697d 100644 (file)
@@ -9,7 +9,7 @@
                </style>
                <style id="__sfc-styles"></style>
                <script type="module">
-                       let scriptEl
+                       let scriptEls = []
 
                        window.__modules__ = {}
 
                                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);
                                        }
index 05f6f5fce421af881a176b8b8505a705de4b0985..5a0a5d0502732bd1349b661d5aac9a5620dd8f2e 100644 (file)
@@ -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() {
index 1e4c047250541f39983ac1a3f1b0e052be839a41..7aea0edbed7bebf5ad0760b74fd38f92deb8abb4 100644 (file)
@@ -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'