chore(sfc-playground): enable ref transform
This commit is contained in:
parent
6453359852
commit
80ed275073
@ -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>
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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]
|
Loading…
Reference in New Issue
Block a user