]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
workflow(sfc-playground): support selecting versions
authorEvan You <yyx990803@gmail.com>
Wed, 31 Mar 2021 02:00:46 +0000 (22:00 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 31 Mar 2021 02:00:46 +0000 (22:00 -0400)
packages/sfc-playground/package.json
packages/sfc-playground/src/App.vue
packages/sfc-playground/src/Header.vue
packages/sfc-playground/src/sfcCompiler.ts
yarn.lock

index 7f9473ed11c11f2054cbe25657fca2942a6ca0ff..27d5c7a8edec8d73b0ffbb5e39701a33a0f080d9 100644 (file)
@@ -18,7 +18,7 @@
     "@types/codemirror": "^0.0.108",
     "@vitejs/plugin-vue": "^1.2.0",
     "codemirror": "^5.60.0",
-    "vite": "^2.1.4"
+    "vite": "^2.1.5"
   },
   "dependencies": {
     "file-saver": "^2.0.5",
index d2f1693212678d0725fefcc71cd8c5dd11bfd286..cf4424ad69443f845db9f144423dced2a7787289 100644 (file)
@@ -24,9 +24,10 @@ body {
   font-size: 13px;
   font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
     Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
-  color: #444;
+  color:var(--base);
   margin: 0;
   background-color: #f8f8f8;
+  --base: #444;
   --nav-height: 50px;
   --font-code: 'Source Code Pro', monospace;
   --color-branding: #3ca877;
index 8ec6b1188c3b35b1253c042a2acfea17d7c20c8f..9c408e16a7c99e76cfe4ad97f4252a21f8996667 100644 (file)
@@ -5,9 +5,21 @@
       <span>Vue SFC Playground</span>
     </h1>
     <div class="links">
-      <a class="commit-link" href="https://app.netlify.com/sites/vue-sfc-playground/deploys" target="_blank">
-        @{{ commit }}
-      </a>
+      <div class="version" @click.stop>
+        <span class="active-version" @click="toggle">
+          Version: {{ activeVersion }}
+        </span>
+        <ul class="versions" :class="{ expanded }">
+          <li v-if="!publishedVersions"><a>loading versions...</a></li>
+          <li v-for="version of publishedVersions">
+            <a @click="setVueVersion(version)">v{{ version }}</a>
+          </li>
+          <li><a @click="resetVueVersion">This Commit ({{ commit }})</a></li>
+          <li>
+            <a href="https://app.netlify.com/sites/vue-sfc-playground/deploys" target="_blank">Commits History</a>
+          </li>
+        </ul>
+      </div>
       <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">
 
 <script setup lang="ts">
 import { downloadProject } from './download/download'
+import { setVersion, resetVersion } from './sfcCompiler'
+import { ref, onMounted } from 'vue'
 
 const commit = __COMMIT__
+const activeVersion = ref(`@${commit}`)
+const publishedVersions = ref<string[]>()
+const expanded = ref(false)
+
+async function toggle() {
+  expanded.value = !expanded.value
+  if (!publishedVersions.value) {
+    publishedVersions.value = await fetchVersions()
+  }
+}
+
+async function setVueVersion(v: string) {
+  activeVersion.value = `loading...`
+  await setVersion(v)
+  activeVersion.value = `v${v}`
+  expanded.value = false
+}
+
+function resetVueVersion() {
+  resetVersion()
+  activeVersion.value = `@${commit}`
+  expanded.value = false
+}
 
 async function copyLink() {
   await navigator.clipboard.writeText(location.href)
   alert('Sharable URL has been copied to clipboard.')
 }
+
+onMounted(async () => {
+  window.addEventListener('click', () => {
+    expanded.value = false
+  })
+})
+
+async function fetchVersions(): Promise<string[]> {
+  const res = await fetch(
+    `https://api.github.com/repos/vuejs/vue-next/releases?per_page=100`
+  )
+  const releases: any[] = await res.json()
+  const versions = releases.map(
+    r => (/^v/.test(r.tag_name) ? r.tag_name.substr(1) : r.tag_name)
+  )
+  const minVersion = versions.findIndex(v => v === '3.0.10')
+  return versions.slice(0, minVersion + 1)
+}
 </script>
 
 <style>
@@ -74,33 +129,81 @@ h1 img {
   top: -2px;
 }
 
-@media (max-width:400px) {
+@media (max-width: 400px) {
   h1 span {
     display: none;
   }
 }
 
-.commit-link {
-  color: var(--color-branding);
-  text-decoration: none;
-  margin-left: 6px;
-  vertical-align: middle;
-  line-height: var(--nav-height);
+.links {
+  display: flex;
 }
 
-.share {
+.version {
+  display: inline-block;
+  margin-right: 12px;
   position: relative;
-  top: 6px;
-  margin: 0 2px;
 }
 
-.download {
+.active-version {
+  cursor: pointer;
   position: relative;
-  top: 8px;
-  margin: 0 2px;
+  display: inline-block;
+  vertical-align: middle;
+  line-height: var(--nav-height);
+  padding-right: 15px;
+}
+
+.active-version:after {
+  content: '';
+  width: 0;
+  height: 0;
+  border-left: 4px solid transparent;
+  border-right: 4px solid transparent;
+  border-top: 6px solid #aaa;
+  position: absolute;
+  right: 0;
+  top: 22px;
+}
+
+.version:hover .active-version:after {
+  border-top-color: var(--base);
 }
 
-.commit-link {
-  margin: 0 5px;
+.versions {
+  display: none;
+  position: absolute;
+  left: 0;
+  top: 40px;
+  background-color: white;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  list-style-type: none;
+  padding: 8px;
+  margin: 0;
+  width: 200px;
+  max-height: calc(100vh - 70px);
+  overflow: scroll;
+}
+
+.versions a {
+  display: block;
+  padding: 6px 12px;
+  text-decoration: none;
+  cursor: pointer;
+  color: var(--base);
+}
+
+.versions a:hover {
+  color: var(--color-branding);
+}
+
+.versions.expanded {
+  display: block;
+}
+
+.share,
+.download {
+  margin: 0 2px;
 }
 </style>
index 15b24e4c02bd57555b124575b5b5e293b2cecaa4..dc586632870fe41bf46d3f44924aabd7f0150b54 100644 (file)
@@ -1,22 +1,40 @@
 import { store, File } from './store'
-import {
-  parse,
-  compileTemplate,
-  compileStyleAsync,
-  compileScript,
-  rewriteDefault,
-  SFCDescriptor,
-  BindingMetadata
-} from '@vue/compiler-sfc'
+import { SFCDescriptor, BindingMetadata } from '@vue/compiler-sfc'
+import * as defaultCompiler from '@vue/compiler-sfc'
 
 export const MAIN_FILE = 'App.vue'
 export const COMP_IDENTIFIER = `__sfc__`
 
+/**
+ * The default SFC compiler we are using is built from each commit
+ * but we may swap it out with a version fetched from CDNs
+ */
+let SFCCompiler: typeof defaultCompiler = defaultCompiler
+
 // @ts-ignore
-export const SANDBOX_VUE_URL = import.meta.env.PROD
+const defaultVueUrl = import.meta.env.PROD
   ? '/vue.runtime.esm-browser.js' // to be copied on build
   : '/src/vue-dev-proxy'
 
+export let SANDBOX_VUE_URL = defaultVueUrl
+
+export async function setVersion(version: string) {
+  const compilerUrl = `https://unpkg.com/@vue/compiler-sfc@${version}/dist/compiler-sfc.esm-browser.js`
+  const runtimeUrl = `https://cdn.skypack.dev/@vue/runtime-dom@${version}`
+  const [compiler] = await Promise.all([
+    import(/* @vite-ignore */ compilerUrl),
+    import(/* @vite-ignore */ runtimeUrl)
+  ])
+  SFCCompiler = compiler
+  SANDBOX_VUE_URL = runtimeUrl
+  console.info(`Now using Vue version: ${version}`)
+}
+
+export function resetVersion() {
+  SFCCompiler = defaultCompiler
+  SANDBOX_VUE_URL = defaultVueUrl
+}
+
 export async function compileFile({ filename, code, compiled }: File) {
   if (!code.trim()) {
     store.errors = []
@@ -30,7 +48,10 @@ export async function compileFile({ filename, code, compiled }: File) {
   }
 
   const id = await hashId(filename)
-  const { errors, descriptor } = parse(code, { filename, sourceMap: true })
+  const { errors, descriptor } = SFCCompiler.parse(code, {
+    filename,
+    sourceMap: true
+  })
   if (errors.length) {
     store.errors = errors
     return
@@ -121,7 +142,7 @@ export async function compileFile({ filename, code, compiled }: File) {
       return
     }
 
-    const styleResult = await compileStyleAsync({
+    const styleResult = await SFCCompiler.compileStyleAsync({
       source: style.content,
       filename,
       id,
@@ -156,7 +177,7 @@ function doCompileScript(
 ): [string, BindingMetadata | undefined] | undefined {
   if (descriptor.script || descriptor.scriptSetup) {
     try {
-      const compiledScript = compileScript(descriptor, {
+      const compiledScript = SFCCompiler.compileScript(descriptor, {
         id,
         refSugar: true,
         inlineTemplate: true,
@@ -173,7 +194,9 @@ function doCompileScript(
           2
         )} */`
       }
-      code += `\n` + rewriteDefault(compiledScript.content, COMP_IDENTIFIER)
+      code +=
+        `\n` +
+        SFCCompiler.rewriteDefault(compiledScript.content, COMP_IDENTIFIER)
       return [code, compiledScript.bindings]
     } catch (e) {
       store.errors = [e]
@@ -190,7 +213,7 @@ function doCompileTemplate(
   bindingMetadata: BindingMetadata | undefined,
   ssr: boolean
 ) {
-  const templateResult = compileTemplate({
+  const templateResult = SFCCompiler.compileTemplate({
     source: descriptor.template!.content,
     filename: descriptor.filename,
     id,
index 2eb346a08142953143be7fc02f9001e1b99dfef8..285bf02127d1ac45d65018eccec991c3c2453310 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
@@ -7223,10 +7223,10 @@ verror@1.10.0:
     core-util-is "1.0.2"
     extsprintf "^1.2.0"
 
-vite@^2.1.4:
-  version "2.1.4"
-  resolved "https://registry.yarnpkg.com/vite/-/vite-2.1.4.tgz#66396823701e54cf3bfb9f73dbd386c9b4329c86"
-  integrity sha512-j/p0RZQvNY/auSPfazsDfo1PHtFp8ktwXPbzI6NqplzHcR3Cn/dfQWiMxL6zp8j9IWdcJP1Zfms7mxruBhStJw==
+vite@^2.1.5:
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/vite/-/vite-2.1.5.tgz#4857da441c62f7982c83cbd5f42a00330f20c9c1"
+  integrity sha512-tYU5iaYeUgQYvK/CNNz3tiJ8vYqPWfCE9IQ7K0iuzYovWw7lzty7KRYGWwV3CQPh0NKxWjOczAqiJsCL0Xb+Og==
   dependencies:
     esbuild "^0.9.3"
     postcss "^8.2.1"