Skip to content

Commit 80ed275

Browse files
committed
chore(sfc-playground): enable ref transform
1 parent 6453359 commit 80ed275

File tree

6 files changed

+91
-115
lines changed

6 files changed

+91
-115
lines changed

packages/sfc-playground/src/Header.vue

+48-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
22
import { downloadProject } from './download/download'
3-
import { setVersion, resetVersion } from './sfcCompiler'
3+
import { setVersion, resetVersion } from './transform'
44
import { ref, onMounted } from 'vue'
55
66
const currentCommit = __COMMIT__
@@ -44,8 +44,8 @@ async function fetchVersions(): Promise<string[]> {
4444
`https://api.github.com/repos/vuejs/vue-next/releases?per_page=100`
4545
)
4646
const releases: any[] = await res.json()
47-
const versions = releases.map(
48-
r => (/^v/.test(r.tag_name) ? r.tag_name.substr(1) : r.tag_name)
47+
const versions = releases.map(r =>
48+
/^v/.test(r.tag_name) ? r.tag_name.substr(1) : r.tag_name
4949
)
5050
const minVersion = versions.findIndex(v => v === '3.0.10')
5151
return versions.slice(0, minVersion + 1)
@@ -55,7 +55,7 @@ async function fetchVersions(): Promise<string[]> {
5555
<template>
5656
<nav>
5757
<h1>
58-
<img alt="logo" src="/logo.svg">
58+
<img alt="logo" src="/logo.svg" />
5959
<span>Vue SFC Playground</span>
6060
</h1>
6161
<div class="links">
@@ -68,31 +68,61 @@ async function fetchVersions(): Promise<string[]> {
6868
<li v-for="version of publishedVersions">
6969
<a @click="setVueVersion(version)">v{{ version }}</a>
7070
</li>
71-
<li><a @click="resetVueVersion">This Commit ({{ currentCommit }})</a></li>
7271
<li>
73-
<a href="https://app.netlify.com/sites/vue-sfc-playground/deploys" target="_blank">Commits History</a>
72+
<a @click="resetVueVersion">This Commit ({{ currentCommit }})</a>
73+
</li>
74+
<li>
75+
<a
76+
href="https://app.netlify.com/sites/vue-sfc-playground/deploys"
77+
target="_blank"
78+
>Commits History</a
79+
>
7480
</li>
7581
</ul>
7682
</div>
7783
<button class="share" @click="copyLink">
7884
<svg width="1.4em" height="1.4em" viewBox="0 0 24 24">
79-
<g fill="none" stroke="#626262" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
80-
<circle cx="18" cy="5" r="3"/>
81-
<circle cx="6" cy="12" r="3"/>
82-
<circle cx="18" cy="19" r="3"/>
83-
<path d="M8.59 13.51l6.83 3.98"/>
84-
<path d="M15.41 6.51l-6.82 3.98"/>
85+
<g
86+
fill="none"
87+
stroke="#626262"
88+
stroke-width="2"
89+
stroke-linecap="round"
90+
stroke-linejoin="round"
91+
>
92+
<circle cx="18" cy="5" r="3" />
93+
<circle cx="6" cy="12" r="3" />
94+
<circle cx="18" cy="19" r="3" />
95+
<path d="M8.59 13.51l6.83 3.98" />
96+
<path d="M15.41 6.51l-6.82 3.98" />
8597
</g>
8698
</svg>
87-
</button>
99+
</button>
88100
<button class="download" @click="downloadProject">
89101
<svg width="1.7em" height="1.7em" viewBox="0 0 24 24">
90102
<g fill="#626262">
91-
<rect x="4" y="18" width="16" height="2" rx="1" ry="1"/>
92-
<rect x="3" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 5 18)"/>
93-
<rect x="17" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 19 18)"/>
94-
<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"/>
95-
<path d="M12 13a1 1 0 0 1-1-1V4a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1z"/>
103+
<rect x="4" y="18" width="16" height="2" rx="1" ry="1" />
104+
<rect
105+
x="3"
106+
y="17"
107+
width="4"
108+
height="2"
109+
rx="1"
110+
ry="1"
111+
transform="rotate(-90 5 18)"
112+
/>
113+
<rect
114+
x="17"
115+
y="17"
116+
width="4"
117+
height="2"
118+
rx="1"
119+
ry="1"
120+
transform="rotate(-90 19 18)"
121+
/>
122+
<path
123+
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"
124+
/>
125+
<path d="M12 13a1 1 0 0 1-1-1V4a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1z" />
96126
</g>
97127
</svg>
98128
</button>

packages/sfc-playground/src/editor/FileSelector.vue

+2-6
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,9 @@ function focus({ el }: VNode) {
2020
function doneAddFile() {
2121
const filename = pendingFilename.value
2222
23-
if (
24-
!filename.endsWith('.vue') &&
25-
!filename.endsWith('.js') &&
26-
filename !== 'import-map.json'
27-
) {
23+
if (!/\.(vue|js|ts)$/.test(filename) && filename !== 'import-map.json') {
2824
store.errors = [
29-
`Playground only supports *.vue, *.js files or import-map.json.`
25+
`Playground only supports *.vue, *.js, *.ts files or import-map.json.`
3026
]
3127
return
3228
}

packages/sfc-playground/src/output/Preview.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from 'vue'
1111
import srcdoc from './srcdoc.html?raw'
1212
import { PreviewProxy } from './PreviewProxy'
13-
import { MAIN_FILE, vueRuntimeUrl } from '../sfcCompiler'
13+
import { MAIN_FILE, vueRuntimeUrl } from '../transform'
1414
import { compileModulesForPreview } from './moduleCompiler'
1515
import { store } from '../store'
1616

packages/sfc-playground/src/output/moduleCompiler.ts

+10-80
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { store, File } from '../store'
2-
import { MAIN_FILE } from '../sfcCompiler'
2+
import { MAIN_FILE } from '../transform'
3+
import { babelParse, MagicString, walk } from '@vue/compiler-sfc'
34
import {
4-
babelParse,
5-
MagicString,
6-
walk,
7-
walkIdentifiers
8-
} from '@vue/compiler-sfc'
5+
walkIdentifiers,
6+
extractIdentifiers,
7+
isInDestructureAssignment,
8+
isStaticProperty
9+
} from '@vue/compiler-core'
910
import { babelParserDefaultPlugins } from '@vue/shared'
10-
import { ExportSpecifier, Identifier, Node, ObjectProperty } from '@babel/types'
11+
import { ExportSpecifier, Identifier, Node } from '@babel/types'
1112

1213
export function compileModulesForPreview() {
1314
return processFile(store.files[MAIN_FILE]).reverse()
@@ -110,9 +111,8 @@ function processFile(file: File, seen = new Set<File>()) {
110111
} else if (node.declaration.type === 'VariableDeclaration') {
111112
// export const foo = 1, bar = 2
112113
for (const decl of node.declaration.declarations) {
113-
const names = extractNames(decl.id as any)
114-
for (const name of names) {
115-
defineExport(name)
114+
for (const id of extractIdentifiers(decl.id)) {
115+
defineExport(id.name)
116116
}
117117
}
118118
}
@@ -231,73 +231,3 @@ function processFile(file: File, seen = new Set<File>()) {
231231
// return a list of files to further process
232232
return processed
233233
}
234-
235-
const isStaticProperty = (node: Node): node is ObjectProperty =>
236-
node.type === 'ObjectProperty' && !node.computed
237-
238-
function extractNames(param: Node): string[] {
239-
return extractIdentifiers(param).map(id => id.name)
240-
}
241-
242-
function extractIdentifiers(
243-
param: Node,
244-
nodes: Identifier[] = []
245-
): Identifier[] {
246-
switch (param.type) {
247-
case 'Identifier':
248-
nodes.push(param)
249-
break
250-
251-
case 'MemberExpression':
252-
let object: any = param
253-
while (object.type === 'MemberExpression') {
254-
object = object.object
255-
}
256-
nodes.push(object)
257-
break
258-
259-
case 'ObjectPattern':
260-
param.properties.forEach(prop => {
261-
if (prop.type === 'RestElement') {
262-
extractIdentifiers(prop.argument, nodes)
263-
} else {
264-
extractIdentifiers(prop.value, nodes)
265-
}
266-
})
267-
break
268-
269-
case 'ArrayPattern':
270-
param.elements.forEach(element => {
271-
if (element) extractIdentifiers(element, nodes)
272-
})
273-
break
274-
275-
case 'RestElement':
276-
extractIdentifiers(param.argument, nodes)
277-
break
278-
279-
case 'AssignmentPattern':
280-
extractIdentifiers(param.left, nodes)
281-
break
282-
}
283-
284-
return nodes
285-
}
286-
287-
function isInDestructureAssignment(parent: Node, parentStack: Node[]): boolean {
288-
if (
289-
parent &&
290-
(parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')
291-
) {
292-
let i = parentStack.length
293-
while (i--) {
294-
const p = parentStack[i]
295-
if (p.type === 'AssignmentExpression') {
296-
return true
297-
} else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {
298-
break
299-
}
300-
}
301-
}
302-
return false
303-
}

packages/sfc-playground/src/store.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { reactive, watchEffect } from 'vue'
2-
import { compileFile, MAIN_FILE } from './sfcCompiler'
2+
import { compileFile, MAIN_FILE } from './transform'
33
import { utoa, atou } from './utils'
44

55
const welcomeCode = `
6+
<script setup>
7+
import { ref } from 'vue'
8+
9+
const msg = ref('Hello World!')
10+
</script>
11+
612
<template>
713
<h1>{{ msg }}</h1>
14+
<input v-model="msg">
815
</template>
9-
10-
<script setup>
11-
const msg = 'Hello World!'
12-
</script>
1316
`.trim()
1417

1518
export class File {

packages/sfc-playground/src/sfcCompiler.ts renamed to packages/sfc-playground/src/transform.ts

+22-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { store, File } from './store'
2-
import { SFCDescriptor, BindingMetadata } from '@vue/compiler-sfc'
2+
import {
3+
SFCDescriptor,
4+
BindingMetadata,
5+
shouldTransformRef,
6+
transformRef
7+
} from '@vue/compiler-sfc'
38
import * as defaultCompiler from '@vue/compiler-sfc'
49
import { ref } from 'vue'
510

@@ -36,13 +41,27 @@ export function resetVersion() {
3641
vueRuntimeUrl.value = defaultVueUrl
3742
}
3843

44+
async function transformTS(src: string) {
45+
return (await import('sucrase')).transform(src, {
46+
transforms: ['typescript']
47+
}).code
48+
}
49+
3950
export async function compileFile({ filename, code, compiled }: File) {
4051
if (!code.trim()) {
4152
store.errors = []
4253
return
4354
}
4455

4556
if (!filename.endsWith('.vue')) {
57+
if (shouldTransformRef(code)) {
58+
code = transformRef(code, { filename }).code
59+
}
60+
61+
if (filename.endsWith('.ts')) {
62+
code = await transformTS(code)
63+
}
64+
4665
compiled.js = compiled.ssr = code
4766
store.errors = []
4867
return
@@ -190,7 +209,7 @@ async function doCompileScript(
190209
try {
191210
const compiledScript = SFCCompiler.compileScript(descriptor, {
192211
id,
193-
refSugar: true,
212+
refTransform: true,
194213
inlineTemplate: true,
195214
templateOptions: {
196215
ssr,
@@ -210,9 +229,7 @@ async function doCompileScript(
210229
SFCCompiler.rewriteDefault(compiledScript.content, COMP_IDENTIFIER)
211230

212231
if ((descriptor.script || descriptor.scriptSetup)!.lang === 'ts') {
213-
code = (await import('sucrase')).transform(code, {
214-
transforms: ['typescript']
215-
}).code
232+
code = await transformTS(code)
216233
}
217234

218235
return [code, compiledScript.bindings]

0 commit comments

Comments
 (0)