11import { types as t } from '@babel/core'
22import { camelize , capitalize } from '@vue/shared'
3- import traverse from '@babel/traverse '
3+ import { Node , Statement } from '@babel/types '
44import generate from '@babel/generator'
5+ import { partition } from '@antfu/utils'
56import { ParsedSFC , ScriptSetupTransformOptions } from '../types'
67import { applyMacros } from './macros'
78import { getIdentifierDeclarations } from './identifiers'
89
910export function transformScriptSetup ( sfc : ParsedSFC , options ?: ScriptSetupTransformOptions ) {
1011 const { scriptSetup, script, template } = sfc
1112
12- const imports = scriptSetup . ast . body . filter ( n => n . type === 'ImportDeclaration' )
13- const body = scriptSetup . ast . body . filter ( n => n . type !== 'ImportDeclaration' )
13+ const { nodes : body , props } = applyMacros ( scriptSetup . ast . body )
1414
15- const { nodes : scriptSetupBody , props } = applyMacros ( body )
15+ const [ hoisted , setupBody ] = partition (
16+ body ,
17+ n => n . type === 'ImportDeclaration'
18+ || n . type === 'ExportNamedDeclaration'
19+ || n . type . startsWith ( 'TS' ) ,
20+ )
1621
1722 // get all identifiers in `<script setup>`
1823 const declarations = new Set < string > ( )
19- getIdentifierDeclarations ( imports , declarations )
20- getIdentifierDeclarations ( body , declarations )
24+ getIdentifierDeclarations ( hoisted , declarations )
25+ getIdentifierDeclarations ( setupBody , declarations )
2126
2227 // filter out identifiers that are used in `<template>`
2328 const returns = Array . from ( declarations )
@@ -31,31 +36,28 @@ export function transformScriptSetup(sfc: ParsedSFC, options?: ScriptSetupTransf
3136 )
3237
3338 // append `<script setup>` imports to `<script>`
34- let ast = t . program ( [
35- ...imports ,
36- ...script . ast . body ,
37- ] )
3839
3940 const __sfc = t . identifier ( '__sfc_main' )
4041
4142 let hasBody = false
4243
43- // replace `export default` with a temproray variable
44- // `const __sfc_main = { ... }`
45- traverse ( ast , {
46- ExportDefaultDeclaration ( path ) {
47- hasBody = true
48- const decl = path . node . declaration
49- path . replaceWith (
50- t . variableDeclaration ( 'const' , [
51- t . variableDeclarator (
52- __sfc ,
53- decl as any ,
54- ) ,
55- ] ) ,
56- )
57- } ,
58- } )
44+ let ast = t . program (
45+ [ ...hoisted , ...script . ast . body ]
46+ . map ( ( node : Node ) => {
47+ // replace `export default` with a temproray variable
48+ // `const __sfc_main = { ... }`
49+ if ( node . type === 'ExportDefaultDeclaration' ) {
50+ hasBody = true
51+ return t . variableDeclaration ( 'const' , [
52+ t . variableDeclarator (
53+ __sfc ,
54+ node . declaration as any ,
55+ ) ,
56+ ] )
57+ }
58+ return node
59+ } ) as Statement [ ] ,
60+ )
5961
6062 // inject `const __sfc_main = {}` if `<script>` has default export
6163 if ( ! hasBody ) {
@@ -104,7 +106,7 @@ export function transformScriptSetup(sfc: ParsedSFC, options?: ScriptSetupTransf
104106 t . identifier ( '__props' ) ,
105107 t . identifier ( '__ctx' ) ,
106108 ] , t . blockStatement ( [
107- ...scriptSetupBody ,
109+ ...setupBody ,
108110 returnStatement as any ,
109111 ] ) ) ,
110112 ) ,
0 commit comments