]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
chore(sfc-playground): enable ref transform
authorEvan You <yyx990803@gmail.com>
Mon, 23 Aug 2021 16:21:17 +0000 (12:21 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 23 Aug 2021 16:21:17 +0000 (12:21 -0400)
packages/sfc-playground/src/Header.vue
packages/sfc-playground/src/editor/FileSelector.vue
packages/sfc-playground/src/output/Preview.vue
packages/sfc-playground/src/output/moduleCompiler.ts
packages/sfc-playground/src/store.ts
packages/sfc-playground/src/transform.ts [moved from packages/sfc-playground/src/sfcCompiler.ts with 93% similarity]

index e365476ef6f392a6d826e984fd7b5cbbdbb01fb6..1afa9b53fdb52832f2941866900834878d3ecd90 100644 (file)
@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import { downloadProject } from './download/download'
-import { setVersion, resetVersion } from './sfcCompiler'
+import { setVersion, resetVersion } from './transform'
 import { ref, onMounted } from 'vue'
 
 const currentCommit = __COMMIT__
@@ -44,8 +44,8 @@ async function fetchVersions(): Promise<string[]> {
     `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 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)
@@ -55,7 +55,7 @@ async function fetchVersions(): Promise<string[]> {
 <template>
   <nav>
     <h1>
-      <img alt="logo" src="/logo.svg">
+      <img alt="logo" src="/logo.svg" />
       <span>Vue SFC Playground</span>
     </h1>
     <div class="links">
@@ -68,31 +68,61 @@ async function fetchVersions(): Promise<string[]> {
           <li v-for="version of publishedVersions">
             <a @click="setVueVersion(version)">v{{ version }}</a>
           </li>
-          <li><a @click="resetVueVersion">This Commit ({{ currentCommit }})</a></li>
           <li>
-            <a href="https://app.netlify.com/sites/vue-sfc-playground/deploys" target="_blank">Commits History</a>
+            <a @click="resetVueVersion">This Commit ({{ currentCommit }})</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">
-            <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
+            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>
       <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"/>
+            <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>
index b742a33a51d930f184871b813a0a6a667ef27ef7..aee2309eaa64c63fa02a33c68f11bac323c68f6c 100644 (file)
@@ -20,13 +20,9 @@ function focus({ el }: VNode) {
 function doneAddFile() {
   const filename = pendingFilename.value
 
-  if (
-    !filename.endsWith('.vue') &&
-    !filename.endsWith('.js') &&
-    filename !== 'import-map.json'
-  ) {
+  if (!/\.(vue|js|ts)$/.test(filename) && filename !== 'import-map.json') {
     store.errors = [
-      `Playground only supports *.vue, *.js files or import-map.json.`
+      `Playground only supports *.vue, *.js, *.ts files or import-map.json.`
     ]
     return
   }
index e6808602869a562ebe120eea49b2621c74d489d0..a63acc062f7aef8c97c4303b41e3733b9c5c4a6c 100644 (file)
@@ -10,7 +10,7 @@ import {
 } from 'vue'
 import srcdoc from './srcdoc.html?raw'
 import { PreviewProxy } from './PreviewProxy'
-import { MAIN_FILE, vueRuntimeUrl } from '../sfcCompiler'
+import { MAIN_FILE, vueRuntimeUrl } from '../transform'
 import { compileModulesForPreview } from './moduleCompiler'
 import { store } from '../store'
 
index 89062897375e650305d2dc7a355a5371713dfd0f..27bc7254478b5a6c6b1cb253c8ae877d0eed9e60 100644 (file)
@@ -1,13 +1,14 @@
 import { store, File } from '../store'
-import { MAIN_FILE } from '../sfcCompiler'
+import { MAIN_FILE } from '../transform'
+import { babelParse, MagicString, walk } from '@vue/compiler-sfc'
 import {
-  babelParse,
-  MagicString,
-  walk,
-  walkIdentifiers
-} from '@vue/compiler-sfc'
+  walkIdentifiers,
+  extractIdentifiers,
+  isInDestructureAssignment,
+  isStaticProperty
+} from '@vue/compiler-core'
 import { babelParserDefaultPlugins } from '@vue/shared'
-import { ExportSpecifier, Identifier, Node, ObjectProperty } from '@babel/types'
+import { ExportSpecifier, Identifier, Node } from '@babel/types'
 
 export function compileModulesForPreview() {
   return processFile(store.files[MAIN_FILE]).reverse()
@@ -110,9 +111,8 @@ function processFile(file: File, seen = new Set<File>()) {
         } else if (node.declaration.type === 'VariableDeclaration') {
           // export const foo = 1, bar = 2
           for (const decl of node.declaration.declarations) {
-            const names = extractNames(decl.id as any)
-            for (const name of names) {
-              defineExport(name)
+            for (const id of extractIdentifiers(decl.id)) {
+              defineExport(id.name)
             }
           }
         }
@@ -231,73 +231,3 @@ function processFile(file: File, seen = new Set<File>()) {
   // return a list of files to further process
   return processed
 }
-
-const isStaticProperty = (node: Node): node is ObjectProperty =>
-  node.type === 'ObjectProperty' && !node.computed
-
-function extractNames(param: Node): string[] {
-  return extractIdentifiers(param).map(id => id.name)
-}
-
-function extractIdentifiers(
-  param: Node,
-  nodes: Identifier[] = []
-): Identifier[] {
-  switch (param.type) {
-    case 'Identifier':
-      nodes.push(param)
-      break
-
-    case 'MemberExpression':
-      let object: any = param
-      while (object.type === 'MemberExpression') {
-        object = object.object
-      }
-      nodes.push(object)
-      break
-
-    case 'ObjectPattern':
-      param.properties.forEach(prop => {
-        if (prop.type === 'RestElement') {
-          extractIdentifiers(prop.argument, nodes)
-        } else {
-          extractIdentifiers(prop.value, nodes)
-        }
-      })
-      break
-
-    case 'ArrayPattern':
-      param.elements.forEach(element => {
-        if (element) extractIdentifiers(element, nodes)
-      })
-      break
-
-    case 'RestElement':
-      extractIdentifiers(param.argument, nodes)
-      break
-
-    case 'AssignmentPattern':
-      extractIdentifiers(param.left, nodes)
-      break
-  }
-
-  return nodes
-}
-
-function isInDestructureAssignment(parent: Node, parentStack: Node[]): boolean {
-  if (
-    parent &&
-    (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')
-  ) {
-    let i = parentStack.length
-    while (i--) {
-      const p = parentStack[i]
-      if (p.type === 'AssignmentExpression') {
-        return true
-      } else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {
-        break
-      }
-    }
-  }
-  return false
-}
index b68a7042f4615b9815e48f6890a60dd277a2cb68..7a741bdbf1a94358213c8b1cdf1b5cb98805e523 100644 (file)
@@ -1,15 +1,18 @@
 import { reactive, watchEffect } from 'vue'
-import { compileFile, MAIN_FILE } from './sfcCompiler'
+import { compileFile, MAIN_FILE } from './transform'
 import { utoa, atou } from './utils'
 
 const welcomeCode = `
+<script setup>
+import { ref } from 'vue'
+
+const msg = ref('Hello World!')
+</script>
+
 <template>
   <h1>{{ msg }}</h1>
+  <input v-model="msg">
 </template>
-
-<script setup>
-const msg = 'Hello World!'
-</script>
 `.trim()
 
 export class File {
similarity index 93%
rename from packages/sfc-playground/src/sfcCompiler.ts
rename to packages/sfc-playground/src/transform.ts
index 8fc7b68cec5622131e4ccdb8d6a97ba86dfa25f9..57517f9c34267cc4029adb94bb0a0575dc04a998 100644 (file)
@@ -1,5 +1,10 @@
 import { store, File } from './store'
-import { SFCDescriptor, BindingMetadata } from '@vue/compiler-sfc'
+import {
+  SFCDescriptor,
+  BindingMetadata,
+  shouldTransformRef,
+  transformRef
+} from '@vue/compiler-sfc'
 import * as defaultCompiler from '@vue/compiler-sfc'
 import { ref } from 'vue'
 
@@ -36,6 +41,12 @@ export function resetVersion() {
   vueRuntimeUrl.value = defaultVueUrl
 }
 
+async function transformTS(src: string) {
+  return (await import('sucrase')).transform(src, {
+    transforms: ['typescript']
+  }).code
+}
+
 export async function compileFile({ filename, code, compiled }: File) {
   if (!code.trim()) {
     store.errors = []
@@ -43,6 +54,14 @@ export async function compileFile({ filename, code, compiled }: File) {
   }
 
   if (!filename.endsWith('.vue')) {
+    if (shouldTransformRef(code)) {
+      code = transformRef(code, { filename }).code
+    }
+
+    if (filename.endsWith('.ts')) {
+      code = await transformTS(code)
+    }
+
     compiled.js = compiled.ssr = code
     store.errors = []
     return
@@ -190,7 +209,7 @@ async function doCompileScript(
     try {
       const compiledScript = SFCCompiler.compileScript(descriptor, {
         id,
-        refSugar: true,
+        refTransform: true,
         inlineTemplate: true,
         templateOptions: {
           ssr,
@@ -210,9 +229,7 @@ async function doCompileScript(
         SFCCompiler.rewriteDefault(compiledScript.content, COMP_IDENTIFIER)
 
       if ((descriptor.script || descriptor.scriptSetup)!.lang === 'ts') {
-        code = (await import('sucrase')).transform(code, {
-          transforms: ['typescript']
-        }).code
+        code = await transformTS(code)
       }
 
       return [code, compiledScript.bindings]