main 1aaaf584be97 cached
103 files
109.5 KB
32.9k tokens
50 symbols
1 requests
Download .txt
Repository: antfu/unplugin-vue2-script-setup
Branch: main
Commit: 1aaaf584be97
Files: 103
Total size: 109.5 KB

Directory structure:
gitextract_7eas0mg5/

├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .npmrc
├── .tazerc.json
├── LICENSE
├── README.md
├── esbuild.d.ts
├── examples/
│   └── vue-cli/
│       ├── .npmrc
│       ├── babel.config.js
│       ├── package.json
│       ├── public/
│       │   └── index.html
│       ├── src/
│       │   ├── App.vue
│       │   ├── components/
│       │   │   └── HelloWorld.vue
│       │   ├── main.ts
│       │   └── shims-vue.d.ts
│       ├── tsconfig.json
│       └── vue.config.cjs
├── index.d.ts
├── jest.js
├── nuxt.d.ts
├── package.json
├── playground/
│   ├── index.html
│   ├── package.json
│   ├── src/
│   │   ├── App.vue
│   │   ├── Async.vue
│   │   ├── Bar.vue
│   │   ├── ButtonTest.vue
│   │   ├── Foo.vue
│   │   ├── HelloWorld.vue
│   │   ├── main.ts
│   │   └── shims-vue.d.ts
│   ├── tsconfig.json
│   └── vite.config.ts
├── pnpm-workspace.yaml
├── ref-macros.d.ts
├── rollup.config.mjs
├── rollup.d.ts
├── scripts/
│   └── postbuild.ts
├── shims.d.ts
├── src/
│   ├── core/
│   │   ├── babel.ts
│   │   ├── identifiers.ts
│   │   ├── index.ts
│   │   ├── macros.ts
│   │   ├── options.ts
│   │   ├── parseSFC.ts
│   │   ├── transform.ts
│   │   ├── transformScriptSetup.ts
│   │   ├── transformSfcRefSugar.ts
│   │   └── utils.ts
│   ├── esbuild.ts
│   ├── index.ts
│   ├── lib.ts
│   ├── nuxt.ts
│   ├── rollup.ts
│   ├── types.ts
│   ├── vite.ts
│   └── webpack.ts
├── test/
│   ├── __snapshots__/
│   │   └── transform.test.ts.snap
│   ├── errors.test.ts
│   ├── fixtures/
│   │   ├── AsyncImport.vue
│   │   ├── ComponentsDirectives.vue
│   │   ├── ComponentsDirectivesLocal.vue
│   │   ├── ComponentsLocal.vue
│   │   ├── DynamicStyle.vue
│   │   ├── Empty.vue
│   │   ├── Enum.vue
│   │   ├── HtmlTag.vue
│   │   ├── HtmlTag2.vue
│   │   ├── JSLongComment.vue
│   │   ├── Macros.vue
│   │   ├── MacrosDefineExpose.vue
│   │   ├── MacrosPure.vue
│   │   ├── MacrosType.vue
│   │   ├── MacrosType2.vue
│   │   ├── MacrosType3.vue
│   │   ├── MacrosType4.vue
│   │   ├── MacrosType5.vue
│   │   ├── MacrosType6.vue
│   │   ├── MacrosTypeAny.vue
│   │   ├── Object1.vue
│   │   ├── ObjectDestructure.vue
│   │   ├── Pug1.vue
│   │   ├── RefSugar.ts
│   │   ├── RefSugar.vue
│   │   ├── RefSugarScriptSetup.vue
│   │   ├── ScriptLessThanOrEqualTo.vue
│   │   ├── ScriptOnly.vue
│   │   ├── TemplateOnly.vue
│   │   ├── TemplateOptionalChaining.vue
│   │   ├── VFor.vue
│   │   └── VariableBinding.vue
│   ├── identifiers.test.ts
│   ├── nativeTag.test.ts
│   ├── transform.test.ts
│   └── transform_filter.test.ts
├── tsconfig.json
├── types.d.ts
├── vite.d.ts
└── webpack.d.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintignore
================================================
dist
node_modules
*.vue


================================================
FILE: .eslintrc.json
================================================
{
  "extends": "@antfu"
}


================================================
FILE: .github/FUNDING.yml
================================================
github: [antfu]


================================================
FILE: .github/workflows/release.yml
================================================
name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v2
        with:
          node-version: lts/*
          registry-url: https://registry.npmjs.org/
      - run: npm i -g pnpm @antfu/ni
      - run: nci
      - run: nr test --if-present
      # - run: npm publish --access public
      #   env:
      #     NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
      - run: npx conventional-github-releaser -p angular
        env:
          CONVENTIONAL_GITHUB_RELEASER_TOKEN: ${{secrets.GITHUB_TOKEN}}


================================================
FILE: .github/workflows/test.yml
================================================
name: Test

on:
  push:
    branches:
      - main
      - master

  pull_request:
    branches:
      - main
      - master

jobs:
  build:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        node: [18.x]
        os: [ubuntu-latest, windows-latest, macos-latest]
      fail-fast: false

    steps:
      - uses: actions/checkout@v2

      - name: Install pnpm
        uses: pnpm/action-setup@v2

      - name: Set node version to ${{ matrix.node }}
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node }}
          cache: pnpm

      - uses: actions/checkout@v2

      - name: Install
        run: pnpm i

      - name: Lint
        run: pnpm run lint

      - name: Build
        run: pnpm run build

      - name: Test
        run: pnpm run test

      - name: Build Examples
        run: pnpm run build:examples


================================================
FILE: .gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# Nuxt generate
dist

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless

# IDE
.idea

temp.ts
.output


================================================
FILE: .npmrc
================================================
ignore-workspace-root-check=true
strict-peer-dependencies=false


================================================
FILE: .tazerc.json
================================================
{
  "exclude": [
    "vue",
    "htmlparser2"
  ]
}


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 Anthony Fu <https://github.com/antfu>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# unplugin-vue2-script-setup

[![NPM version](https://img.shields.io/npm/v/unplugin-vue2-script-setup?color=a1b858&label=)](https://www.npmjs.com/package/unplugin-vue2-script-setup)

Bring [`<script setup>`](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to Vue 2. Works for Vite, Nuxt, Vue CLI, Webpack, esbuild and more, powered by [unplugin](https://github.com/unjs/unplugin).

> ⚠️ With the release of [Vue 2.7](https://blog.vuejs.org/posts/vue-2-7-naruto.html), which has Composition API and `<script setup>` built-in, **you no longer need this plugin**. Thereby this plugin has entered maintenance mode and will only support Vue 2.6 or earlier. This project will reach End of Life by the end of 2022.

## Install

```bash
npm i -D unplugin-vue2-script-setup
npm i @vue/composition-api
```

Install [`@vue/composition-api`](https://github.com/vuejs/composition-api) in your App's entry (it enables the `setup()` hook):

```ts
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)
```

<details>
<summary>Vite</summary><br>

```ts
// vite.config.ts
import { defineConfig } from 'vite'
import { createVuePlugin as Vue2 } from 'vite-plugin-vue2'
import ScriptSetup from 'unplugin-vue2-script-setup/vite'

export default defineConfig({
  plugins: [
    Vue2(),
    ScriptSetup({ /* options */ }),
  ],
})
```

Example: [`playground/`](./playground/)

<br></details>

<details>
<summary>Nuxt</summary><br>

> It's built-in in [Nuxt Bridge](https://github.com/nuxt/bridge).

</details>

<details>
<summary>Vue CLI</summary><br>

```ts
// vue.config.js
const ScriptSetup = require('unplugin-vue2-script-setup/webpack').default

module.exports = {
  parallel: false, // disable thread-loader, which is not compactible with this plugin
  configureWebpack: {
    plugins: [
      ScriptSetup({ /* options */ }),
    ],
  },
}
```

Example: [`examples/vue-cli`](./examples/vue-cli)

###### TypeScript

To use TypeScript with Vue CLI, install `@vue/cli-plugin-typescript` but disable the type check:

```bash
npm i -D @vue/cli-plugin-typescript vue-tsc
```

```ts
const ScriptSetup = require('unplugin-vue2-script-setup/webpack').default

module.exports = {
  parallel: false,
  configureWebpack: {
    plugins: [
      ScriptSetup({ /* options */ }),
    ],
  },
  chainWebpack(config) {
    // disable type check and let `vue-tsc` handles it
    config.plugins.delete('fork-ts-checker')
  },
}
```

And then use [`vue-tsc`](https://github.com/johnsoncodehk/volar) to do the type check at build time:

```jsonc
// package.json
{
  "scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-tsc --noEmit && vue-cli-service build"
  }
}
```

<br></details>

<details>
<summary>Webpack</summary><br>

```ts
// webpack.config.js
const ScriptSetup = require('unplugin-vue2-script-setup/webpack').default

module.exports = {
  /* ... */
  plugins: [
    ScriptSetup({ /* options */ }),
  ]
}
```

<br></details>

<details>
<summary>Rollup</summary><br>

```ts
// rollup.config.js
import Vue from 'rollup-plugin-vue'
import ScriptSetup from 'unplugin-vue2-script-setup/rollup'

export default {
  plugins: [
    Vue(),
    ScriptSetup({ /* options */ }),
  ]
}
```

<br></details>

<details>
<summary>esbuild</summary><br>

```ts
// esbuild.config.js
import { build } from 'esbuild'
import ScriptSetup from 'unplugin-vue2-script-setup/esbuild'

build({
  /* ... */
  plugins: [
    ScriptSetup({
      /* options */
    }),
  ],
})
```

<br></details>

<details>
<summary>Jest</summary><br>

```bash
npm i -D vue-jest
```

```ts
// jest.config.js
module.exports = {
  transform: {
    '.*\\.(vue)$': 'unplugin-vue2-script-setup/jest',
  },
}
```

<br></details>

<details>
<summary>JavaScript API</summary><br>

```ts
import { transform } from 'unplugin-vue2-script-setup'

const Vue2SFC = await transform(`
<template>
  <!-- ... -->
</template>

<script setup>
  // ...
</script>
`)
```

<br></details>

## IDE

We recommend using [VS Code](https://code.visualstudio.com/) with [Volar](https://github.com/johnsoncodehk/volar) to get the best experience (You might want to disable Vetur if you have it).

When using Volar, you need to install `@vue/runtime-dom` as devDependencies to make it work on Vue 2.

```bash
npm i -D @vue/runtime-dom
```

[Learn more](https://github.com/johnsoncodehk/volar#using)

###### Global Types

If the global types are missing for your IDE, update your `tsconfig.json` with:

```jsonc
{
  "compilerOptions": {
    "types": [
      "unplugin-vue2-script-setup/types"
    ]
  }
}
```

###### Support Vue 2 template

Volar preferentially supports Vue 3. Vue 3 and Vue 2 template has some different. You need to set the `experimentalCompatMode` option to support Vue 2 template.

```jsonc
{
  "compilerOptions": {
    // ...
  },
  "vueCompilerOptions": {
    "target": 2
  }
}
```

###### ESLint

If you are using ESLint, you might get `@typescript-eslint/no-unused-vars` warning with `<script setup>`. You can disable it and add `noUnusedLocals: true` in your `tsconfig.json`, Volar will infer the real missing locals correctly for you. 

## Configurations

<details>
  <summary>
    Ref Sugar (take 2)
  </summary>

In v0.5.x, we shipped the **experimental** [Ref Sugar (take 2)](https://github.com/vuejs/rfcs/discussions/369) implementation based on Vue 3's [`@vue/reactivity-transform`](https://github.com/vuejs/vue-next/tree/master/packages/reactivity-transform) package. Notice the syntax is not settled yet and might be changed in the future updates. **Use at your own risk!**

To enabled it, pass the option:

```ts
ScriptSetup({
  reactivityTransform: true
})
```

To get TypeScript support, update your `tsconfig.json` with:

```jsonc
{
  "compilerOptions": {
    "types": [
      "unplugin-vue2-script-setup/types",
      "unplugin-vue2-script-setup/ref-macros"
    ]
  }
}
```

</details>

## Recommendations

If you enjoy using `<script setup>`, you might also want to try [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) to improve the DX even further.

## Progress

- [x] PoC
- [x] Components registration
- [x] Compile time macros `defineProps` `defineEmits` `withDefaults` `defineExpose`
- [x] Global types
- [x] Merge with normal scripts
- [x] [Ref Sugar (take 2)](https://github.com/vuejs/rfcs/discussions/369)
- [x] `<template lang="pug">` support
- [x] Vite plugin
- [x] Webpack plugin
- [x] Nuxt module
- [ ] ~~Top-level await~~ (not supported)

## How?

<details>
  <summary>
    👀
  </summary>

![image](https://user-images.githubusercontent.com/11247099/130307245-20f9342e-377b-4565-b55d-1b91741b5c0f.png)

It's made possible by transforming the `<script setup>` syntax back to normal `<script>` and let the Vue 2 SFC compiler handle the rest.

<br></details>

## Sponsors

<p align="center">
  <a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
    <img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>
  </a>
</p>

## License

[MIT](./LICENSE) License © 2021 [Anthony Fu](https://github.com/antfu)


================================================
FILE: esbuild.d.ts
================================================
export { default } from './dist/esbuild'


================================================
FILE: examples/vue-cli/.npmrc
================================================
shamefully-hoist=true


================================================
FILE: examples/vue-cli/babel.config.js
================================================
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
  ],
}


================================================
FILE: examples/vue-cli/package.json
================================================
{
  "name": "vue-cli",
  "private": true,
  "scripts": {
    "type-check": "vue-tsc --noEmit",
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@vue/composition-api": "^1.7.1",
    "core-js": "^3.32.0",
    "vue": "~2.6.14"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^5.0.8",
    "@vue/cli-plugin-typescript": "^5.0.8",
    "@vue/cli-service": "^5.0.8",
    "typescript": "^5.1.6",
    "unplugin-vue2-script-setup": "workspace:*",
    "vue-template-compiler": "~2.6.14",
    "vue-tsc": "^1.8.8"
  }
}


================================================
FILE: examples/vue-cli/public/index.html
================================================
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>


================================================
FILE: examples/vue-cli/src/App.vue
================================================
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
  <div id="app">
    <HelloWorld msg="Welcome to Your Vue.js App" />
  </div>
</template>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


================================================
FILE: examples/vue-cli/src/components/HelloWorld.vue
================================================
<script setup lang="ts">
defineProps<{
  msg: string
}>()
</script>
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div>
</template>
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>


================================================
FILE: examples/vue-cli/src/main.ts
================================================
import Vue from 'vue'
import VueCompositionAPI, { createApp, h } from '@vue/composition-api'
import App from './App.vue'

Vue.config.productionTip = false
Vue.use(VueCompositionAPI)

const app = createApp({
  render: () => h(App),
})

app.mount('#app')


================================================
FILE: examples/vue-cli/src/shims-vue.d.ts
================================================
/// <reference types="unplugin-vue2-script-setup/shims.js" />


================================================
FILE: examples/vue-cli/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "skipLibCheck": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "types": [
      "webpack-env"
    ],
    "lib": [
      "esnext",
      "dom",
      "dom.iterable"
    ]
  },
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules"
  ],
  "vueCompilerOptions": {
    "target": 2
  }
}


================================================
FILE: examples/vue-cli/vue.config.cjs
================================================
const { defineConfig } = require('@vue/cli-service')
const ScriptSetup = require('unplugin-vue2-script-setup/webpack').default

module.exports = defineConfig({
  configureWebpack: {
    plugins: [
      ScriptSetup({
        reactivityTransform: true,
      }),
    ],
  },
  parallel: false,
  chainWebpack(config) {
    // disable type check and let `vue-tsc` handles it
    config.plugins.delete('fork-ts-checker')

    // disable cache for testing, you should remove this in production
    config.module.rule('vue').uses.delete('cache-loader')
    config.module.rule('js').uses.delete('cache-loader')
    config.module.rule('ts').uses.delete('cache-loader')
    config.module.rule('tsx').uses.delete('cache-loader')
  },
})


================================================
FILE: index.d.ts
================================================
export { default } from './dist/index'


================================================
FILE: jest.js
================================================
const { transform } = require('./dist/index')

function requireVueJest() {
  const names = ['@vue/vue2-jest', 'vue-jest']
  for (const name of names) {
    try {
      return require(name)
    }
    catch (e) {
      // Try next module
    }
  }
  throw new Error(`Cannot find a Jest transformer for Vue SFC, you should install one of these packages: ${names.join(', ')}`)
}

module.exports = {
  async process(source, filename, ...args) {
    const transformed = await transform(source, filename)
    const code = transformed ? transformed.code : source
    return requireVueJest().process.call(this, code, filename, ...args)
  },
}


================================================
FILE: nuxt.d.ts
================================================
export { default } from './dist/nuxt'


================================================
FILE: package.json
================================================
{
  "name": "unplugin-vue2-script-setup",
  "version": "0.11.4",
  "packageManager": "pnpm@8.6.11",
  "description": "Bring <script setup> to Vue 2",
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
  "license": "MIT",
  "funding": "https://github.com/sponsors/antfu",
  "homepage": "https://github.com/unplugin/unplugin-vue2-script-setup#readme",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/unplugin/unplugin-vue2-script-setup.git"
  },
  "bugs": {
    "url": "https://github.com/unplugin/unplugin-vue2-script-setup/issues"
  },
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    },
    "./*": "./*",
    "./esbuild": {
      "import": "./dist/esbuild.mjs",
      "require": "./dist/esbuild.js"
    },
    "./jest": "./jest.js",
    "./nuxt": {
      "import": "./dist/nuxt.mjs",
      "require": "./dist/nuxt.js"
    },
    "./rollup": {
      "import": "./dist/rollup.mjs",
      "require": "./dist/rollup.js"
    },
    "./types": {
      "import": "./dist/types.mjs",
      "require": "./dist/types.js"
    },
    "./vite": {
      "import": "./dist/vite.mjs",
      "require": "./dist/vite.js"
    },
    "./webpack": {
      "import": "./dist/webpack.mjs",
      "require": "./dist/webpack.js"
    }
  },
  "main": "dist/index.js",
  "files": [
    "dist",
    "jest.js",
    "*.d.ts"
  ],
  "scripts": {
    "build": "rimraf dist && rollup -c",
    "dev": "rollup -c --watch",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "build:examples": "pnpm -r --filter=!unplugin-vue2-script-setup run build",
    "play": "npm -C playground run dev",
    "prepublishOnly": "nr build",
    "release": "bumpp --commit --push --tag && pnpm publish",
    "test": "vitest",
    "test:update": "vitest -u"
  },
  "peerDependencies": {
    "@vue/composition-api": "*",
    "@vue/runtime-dom": "^3.2.31",
    "pug": "^3.0.2"
  },
  "peerDependenciesMeta": {
    "pug": {
      "optional": true
    }
  },
  "dependencies": {
    "@antfu/utils": "^0.7.5",
    "@babel/core": "^7.22.9",
    "@babel/generator": "^7.22.9",
    "@babel/parser": "^7.22.7",
    "@babel/traverse": "^7.22.8",
    "@babel/types": "^7.22.5",
    "@rollup/pluginutils": "^5.0.2",
    "@vue/compiler-core": "^3.3.4",
    "@vue/compiler-dom": "^3.3.4",
    "@vue/reactivity-transform": "^3.3.4",
    "@vue/shared": "^3.3.4",
    "defu": "^6.1.2",
    "magic-string": "^0.30.2",
    "unplugin": "^1.4.0"
  },
  "devDependencies": {
    "@antfu/eslint-config": "^0.40.0",
    "@antfu/ni": "^0.21.5",
    "@rollup/plugin-alias": "^5.0.0",
    "@rollup/plugin-commonjs": "^25.0.3",
    "@rollup/plugin-json": "^6.0.0",
    "@rollup/plugin-node-resolve": "^15.1.0",
    "@types/babel__core": "^7.20.1",
    "@types/estree": "^1.0.1",
    "@types/node": "^18.17.1",
    "@types/pug": "^2.0.6",
    "@types/ws": "^8.5.5",
    "@vue/composition-api": "^1.7.1",
    "@vue/runtime-dom": "^3.3.4",
    "bumpp": "^9.1.1",
    "esbuild": "^0.18.17",
    "eslint": "^8.46.0",
    "fast-glob": "^3.3.1",
    "pug": "^3.0.2",
    "rimraf": "^5.0.1",
    "rollup": "^3.27.0",
    "rollup-plugin-dts": "^5.3.1",
    "rollup-plugin-esbuild": "^5.0.0",
    "rollup-plugin-typescript2": "^0.35.0",
    "typescript": "^5.1.6",
    "vite": "^4.4.8",
    "vitest": "^0.33.0",
    "webpack": "^5.88.2"
  },
  "pnpm": {
    "overrides": {
      "unplugin-vue2-script-setup": "workspace:*"
    }
  }
}


================================================
FILE: playground/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="icon" href="/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vite App</title>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="./src/main.ts"></script>
</body>
</html>


================================================
FILE: playground/package.json
================================================
{
  "private": true,
  "scripts": {
    "dev": "vite --open",
    "build": "vite build"
  },
  "dependencies": {
    "@vue/composition-api": "^1.7.1",
    "vue": "^2.6.14"
  },
  "devDependencies": {
    "vite": "^4.4.8",
    "vite-plugin-inspect": "^0.7.35",
    "vite-plugin-vue2": "^2.0.3",
    "vue-template-compiler": "~2.6.14"
  }
}


================================================
FILE: playground/src/App.vue
================================================
<script setup lang="ts">
import { defineAsyncComponent } from '@vue/composition-api'
import ButtonTest from './ButtonTest.vue';
import HelloWorld from './HelloWorld.vue'

const AsyncComponent = defineAsyncComponent(() => import('./Async.vue'))

function onUpdate(e: any) {
  // eslint-disable-next-line no-console
  console.log(e)
}
</script>
<template>
  <div>
    <ButtonTest />

    <HelloWorld name="Vue 2" @update="onUpdate" />

    <AsyncComponent />
  </div>
</template>


================================================
FILE: playground/src/Async.vue
================================================
<template>
  <div>Async Component</div>
</template>


================================================
FILE: playground/src/Bar.vue
================================================
<template>
  <div>Bar</div>
</template>


================================================
FILE: playground/src/ButtonTest.vue
================================================
<script setup lang="ts">
import Button from './Foo.vue';
import button from './Foo.vue';
</script>

<template>
  <div>
    <button>{{ Button }}</button>
    <Button>{{ button }}</Button>
  </div>
</template>


================================================
FILE: playground/src/Foo.vue
================================================
<script setup lang="ts">

</script>
<template>
  <div>
    Button Component: <slot></slot>
  </div>
</template>


================================================
FILE: playground/src/HelloWorld.vue
================================================
<script lang="ts">
/* eslint-disable import/first */
export default {
  name: 'App',
}
</script>
<script setup lang="ts">
import { watch } from '@vue/composition-api'
import Foo from './Foo.vue'
import Bar from './Bar.vue'

withDefaults(defineProps<{ msg: string; name: string | number }>(), { msg: 'Hello' })
const emit = defineEmits<{
  (event: 'update', value: number): void
}>()

let count = $ref(0)
// eslint-disable-next-line prefer-const
let doubled = $computed(() => count * 2)

function inc() {
  count += 1
}
function dec() {
  count -= 1
}

const decText = '<b>Dec</b>'

watch(count, value => emit('update', value))
</script>
<template>
  <div>
    <h3>{{ msg }}, {{ name }}</h3>
    <button @click="inc">
      Inc
    </button>
    <div>{{ count }} x 2 = {{ doubled }}</div>
    <button @click="dec()" v-html="decText" />
    <component :is="count > 2 ? Foo : Bar" />
  </div>
</template>


================================================
FILE: playground/src/main.ts
================================================
import Vue from 'vue'
import VueCompositionAPI, { createApp, h } from '@vue/composition-api'
import App from './App.vue'

Vue.use(VueCompositionAPI)

const app = createApp({ render: () => h(App) })

app.mount('#app')


================================================
FILE: playground/src/shims-vue.d.ts
================================================
/// <reference types="unplugin-vue2-script-setup/shims.js" />
/// <reference types="unplugin-vue2-script-setup/ref-macros.js" />


================================================
FILE: playground/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "skipLibCheck": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "types": [
      "webpack-env"
    ],
    "lib": [
      "esnext",
      "dom",
      "dom.iterable"
    ]
  },
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules"
  ],
  "vueCompilerOptions": {
    "experimentalCompatMode": 2
  }
}


================================================
FILE: playground/vite.config.ts
================================================
import { defineConfig } from 'vite'
import { createVuePlugin as Vue2 } from 'vite-plugin-vue2'
import Inspect from 'vite-plugin-inspect'
import { unplugin } from '../src'

const ScriptSetup = unplugin.vite

export default defineConfig({
  plugins: [
    Vue2(),
    Inspect(),
    ScriptSetup({
      reactivityTransform: true,
    }),
  ],
})


================================================
FILE: pnpm-workspace.yaml
================================================
- packages
  - playground
  - examples/*


================================================
FILE: ref-macros.d.ts
================================================
import type {
  ComputedRef,
  Ref,
  ShallowUnwrapRef,
  UnwrapRef,
  WritableComputedOptions,
  WritableComputedRef,
} from '@vue/composition-api'

declare const RefMarker: unique symbol
  type RefValue<T> = T & { [RefMarker]?: any }

declare const ComputedRefMarker: unique symbol
  type ComputedRefValue<T> = T & { [ComputedRefMarker]?: any }

declare const WritableComputedRefMarker: unique symbol
  type WritableComputedRefValue<T> = T & { [WritableComputedRefMarker]?: any }

  type ToRawRefs<T extends object> = {
    [K in keyof T]: T[K] extends ComputedRefValue<infer V>
      ? ComputedRefValue<V>
      : T[K] extends WritableComputedRefValue<infer V>
        ? WritableComputedRef<V>
        : T[K] extends RefValue<infer V>
          ? Ref<V>
          : T[K] extends object
            ? T[K] extends
            | Function
            | Map<any, any>
            | Set<any>
            | WeakMap<any, any>
            | WeakSet<any>
              ? T[K]
              : ToRawRefs<T[K]>
            : T[K];
  }

/**
   * Vue ref transform macro for binding refs as reactive variables.
   */
declare function _$<T>(arg: ComputedRef<T>): ComputedRefValue<T>
declare function _$<T>(
  arg: WritableComputedRef<T>
): WritableComputedRefValue<T>
declare function _$<T>(arg: Ref<T>): RefValue<T>
declare function _$<T extends object>(arg?: T): ShallowUnwrapRef<T>

/**
   * Vue ref transform macro for accessing underlying refs of reactive varaibles.
   */
declare function _$$<T>(value: T): ComputedRef<T>
declare function _$$<T>(
  value: WritableComputedRefValue<T>
): WritableComputedRef<T>
declare function _$$<T>(value: RefValue<T>): Ref<T>
declare function _$$<T extends object>(arg: T): ToRawRefs<T>

declare function _$ref<T>(arg?: T | Ref<T>): RefValue<UnwrapRef<T>>

declare function _$shallowRef<T>(arg?: T): RefValue<T>

declare function _$computed<T>(
  getter: () => T,
  // debuggerOptions?: DebuggerOptions
): ComputedRefValue<T>
declare function _$computed<T>(
  options: WritableComputedOptions<T>,
  // debuggerOptions?: DebuggerOptions
): WritableComputedRefValue<T>

declare global {
  const $: typeof _$
  const $$: typeof _$$
  const $ref: typeof _$ref
  const $shallowRef: typeof _$shallowRef
  const $computed: typeof _$computed
}


================================================
FILE: rollup.config.mjs
================================================
// @ts-check
import * as fs from 'node:fs'
import ts from 'rollup-plugin-esbuild'
import dts from 'rollup-plugin-dts'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import alias from '@rollup/plugin-alias'

/** @type {import('./package.json')} */
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf-8'))

const entries = {
  index: 'src/index.ts',
  webpack: 'src/webpack.ts',
  vite: 'src/vite.ts',
  rollup: 'src/rollup.ts',
  esbuild: 'src/esbuild.ts',
  nuxt: 'src/nuxt.ts',
  types: 'src/types.ts',
}

const external = [
  ...Object.keys(pkg.dependencies),
  ...Object.keys(pkg.peerDependencies),
  'esbuild',
  'rollup',
  'vite',
  'webpack',
  '@nuxt/kit',
]


/** @type {import('rollup').RollupOptions[]} */
export default [
  {
    input: entries,
    external,
    plugins: [
      alias({
        entries: [
          { find: /^node:(.+)$/, replacement: '$1' },
        ],
      }),
      resolve({
        preferBuiltins: true,
      }),
      json(),
      commonjs(),
      ts(),
    ],
    onwarn({ code, message }) {
      if(code === 'EMPTY_BUNDLE') return
      console.error(message)
    },
    output:[
      {
        dir: 'dist',
        format: 'esm',
        sourcemap: 'inline',
        entryFileNames: "[name].mjs",
      },
      {
        dir: 'dist',
        format: 'cjs',
        exports: 'named',
        sourcemap: 'inline',
        entryFileNames: "[name].js",
      },
    ]
  },
  {
    input: entries,
    external,
    plugins: [
      dts({ respectExternal: true }),
    ],
    output: [
      {
        dir: 'dist',
        entryFileNames: "[name].d.mts",
      },
      {
        dir: 'dist',
        entryFileNames: "[name].d.ts",
      },
    ],
  },
]


================================================
FILE: rollup.d.ts
================================================
export { default } from './dist/rollup'


================================================
FILE: scripts/postbuild.ts
================================================
import { basename, resolve } from 'node:path'
import { promises as fs } from 'node:fs'
import fg from 'fast-glob'

async function run() {
  // fix cjs exports
  const files = await fg('*.js', {
    ignore: ['chunk-*'],
    absolute: true,
    cwd: resolve(__dirname, '../dist'),
  })
  for (const file of files) {
    console.log('[postbuild]', basename(file))
    const name = basename(file, '.js')
    let code = await fs.readFile(file, 'utf8')
    code = code.replace('exports.default =', 'module.exports =')
    code += 'exports.default = module.exports;'
    await fs.writeFile(file, code)
    await fs.writeFile(`${name}.d.ts`, `import './shims'\nexport { default } from './dist/${name}'\n`)
  }
}

run()


================================================
FILE: shims.d.ts
================================================
// workaround for Volar to infer the ref type in <template>
// https://github.com/johnsoncodehk/volar/issues/404
declare module '@vue/runtime-dom' {
  export * from '@vue/runtime-dom/dist/runtime-dom'
  export { defineComponent, PropType, ObjectDirective, FunctionDirective } from '@vue/composition-api'
}


================================================
FILE: src/core/babel.ts
================================================
import * as babel from '@babel/core'
import { parse, parseExpression } from '@babel/parser'
import g from '@babel/generator'
import * as babel_traverse from '@babel/traverse'

export const t: typeof babel['types'] = ((babel as any).default || babel).types
export const generate: typeof g = ((g as any).default || g)
export const traverse = ((babel_traverse as any)?.default?.default as null) ?? babel_traverse?.default ?? babel_traverse
export { parseExpression, parse }


================================================
FILE: src/core/identifiers.ts
================================================
import type {
  Expression,
  File,
  PrivateName,
  SpreadElement,
  Statement,
  TSType,
} from '@babel/types'
import type { ParseResult } from '@babel/parser'
import { t, traverse } from './babel'

export function getIdentifierDeclarations(nodes: Statement[]) {
  let result!: Set<string>
  let programScopeUid: number
  traverse(t.file(t.program(nodes)), {
    Program(path) {
      result = new Set(Object.keys(path.scope.bindings))
      programScopeUid = (path.scope as any).uid
    },
    // FIXME: babel bug, temporary add TSEnumDeclaration and TSModuleDeclaration logic
    TSEnumDeclaration(path) {
      if ((path.scope as any).uid === programScopeUid)
        result.add(path.node.id.name)
    },
    TSModuleDeclaration(path) {
      if ((path.scope as any).uid === programScopeUid) {
        const id = path.node.id
        if (id.type === 'Identifier')
          result.add(id.name)
      }
    },
  })
  return Array.from(result)
}

/**
 * @deprecated use `getFileGlobals` instead
 */
export function getIdentifierUsages(node?: Expression | TSType | SpreadElement | PrivateName | Statement | null, identifiers = new Set<string>()) {
  if (!node)
    return identifiers

  if (node.type === 'BlockStatement') {
    node.body.forEach(child => getIdentifierUsages(child, identifiers))
  }
  else if (node.type === 'ExpressionStatement') {
    getIdentifierUsages(node.expression, identifiers)
  }
  else if (node.type === 'Identifier') {
    identifiers.add(node.name)
  }
  else if (node.type === 'MemberExpression' || node.type === 'OptionalMemberExpression') {
    getIdentifierUsages(node.object, identifiers)
    if (node.computed)
      getIdentifierUsages(node.property, identifiers)
  }
  else if (node.type === 'CallExpression' || node.type === 'OptionalCallExpression') {
    getIdentifierUsages(node.callee as Expression, identifiers)
    node.arguments.forEach(arg => getIdentifierUsages(arg as Expression, identifiers))
  }
  else if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') {
    getIdentifierUsages(node.left, identifiers)
    getIdentifierUsages(node.right, identifiers)
  }
  else if (node.type === 'UnaryExpression') {
    getIdentifierUsages(node.argument, identifiers)
  }
  else if (node.type === 'ForOfStatement' || node.type === 'ForInStatement') {
    getIdentifierUsages(node.right, identifiers)
  }
  else if (node.type === 'ConditionalExpression') {
    getIdentifierUsages(node.test, identifiers)
    getIdentifierUsages(node.consequent, identifiers)
    getIdentifierUsages(node.alternate, identifiers)
  }
  else if (node.type === 'ObjectExpression') {
    node.properties.forEach((prop) => {
      if (prop.type === 'ObjectProperty') {
        if (prop.computed)
          getIdentifierUsages(prop.key, identifiers)
        getIdentifierUsages(prop.value as Expression, identifiers)
      }
      else if (prop.type === 'SpreadElement') {
        getIdentifierUsages(prop, identifiers)
      }
    })
  }
  else if (node.type === 'ArrayExpression') {
    node.elements.forEach(element => getIdentifierUsages(element, identifiers))
  }
  else if (node.type === 'SpreadElement' || node.type === 'ReturnStatement') {
    getIdentifierUsages(node.argument, identifiers)
  }
  else if (node.type === 'NewExpression') {
    getIdentifierUsages(node.callee as Expression, identifiers)
    node.arguments.forEach(arg => getIdentifierUsages(arg as Expression, identifiers))
  }
  else if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
    getIdentifierUsages(node.body, identifiers)
  }
  else if (node.type === 'TemplateLiteral') {
    node.expressions.forEach(expr => getIdentifierUsages(expr, identifiers))
  }
  // else {
  //   console.log(node)
  // }
  return identifiers
}

export function getFileGlobals(result: ParseResult<File>) {
  let globals!: Set<string>
  let programScopeUid: number
  traverse(result, {
    Program(path) {
      globals = new Set(Object.keys((path.scope as any).globals))
      programScopeUid = (path.scope as any).uid
    },
    // FIXME: babel bug, temporary add TSEnumDeclaration and TSModuleDeclaration logic
    TSEnumDeclaration(path) {
      if ((path.scope as any).uid === programScopeUid)
        globals.delete(path.node.id.name)
    },
    TSModuleDeclaration(path) {
      if ((path.scope as any).uid === programScopeUid) {
        const id = path.node.id
        if (id.type === 'Identifier')
          globals.delete(id.name)
      }
    },
  })
  return Array.from(globals)
}


================================================
FILE: src/core/index.ts
================================================
export * from './transform'
export * from './transformScriptSetup'
export * from '../types'


================================================
FILE: src/core/macros.ts
================================================
// modified from https://github.com/vuejs/vue-next/blob/main/packages/compiler-sfc/src/compileScript.ts

import type {
  CallExpression,
  Node,
  ObjectExpression,
  ObjectProperty,
  Statement,
  TSFunctionType,
  TSInterfaceBody,
  TSType,
  TSTypeLiteral,
} from '@babel/types'
import { parseExpression, t } from './babel'

// Special compiler macros
const DEFINE_PROPS = 'defineProps'
const DEFINE_EMITS = 'defineEmits'
const DEFINE_EXPOSE = 'defineExpose'
const WITH_DEFAULTS = 'withDefaults'
const DEFINE_SLOTS = 'defineSlots'

export interface PropTypeData {
  key: string
  type: string[] | string
  required: boolean
}

export function applyMacros(nodes: Statement[]) {
  let hasDefinePropsCall = false
  let hasDefineEmitCall = false
  let hasDefineSlotsCall = false
  let propsRuntimeDecl: Node | undefined
  let propsRuntimeDefaults: Node | undefined
  let propsTypeDecl: TSTypeLiteral | TSInterfaceBody | undefined
  let propsTypeDeclRaw: Node | undefined
  let emitsRuntimeDecl: Node | undefined
  let emitsTypeDecl:
  | TSFunctionType
  | TSTypeLiteral
  | TSInterfaceBody
  | undefined
  let emitsTypeDeclRaw: Node | undefined
  let exposeDecl: CallExpression['arguments'][number] | undefined

  // props/emits declared via types
  const typeDeclaredProps: Record<string, PropTypeData> = {}
  // record declared types for runtime props type generation
  const declaredTypes: Record<string, string[]> = {}

  function error(
    msg: string,

    _node: Node,
  ): never {
    throw new Error(msg)
  }

  function processDefineProps(node: Node): boolean {
    if (!isCallOf(node, DEFINE_PROPS))
      return false

    if (hasDefinePropsCall)
      error(`duplicate ${DEFINE_PROPS}() call`, node)

    hasDefinePropsCall = true

    propsRuntimeDecl = node.arguments[0]

    // call has type parameters - infer runtime types from it
    if (node.typeParameters) {
      if (propsRuntimeDecl) {
        error(
          `${DEFINE_PROPS}() cannot accept both type and non-type arguments `
            + 'at the same time. Use one or the other.',
          node,
        )
      }

      propsTypeDeclRaw = node.typeParameters.params[0]
      propsTypeDecl = resolveQualifiedType(
        propsTypeDeclRaw,
        node => node.type === 'TSTypeLiteral',
      ) as TSTypeLiteral | TSInterfaceBody | undefined

      if (!propsTypeDecl) {
        error(
          `type argument passed to ${DEFINE_PROPS}() must be a literal type, `
            + 'or a reference to an interface or literal type.',
          propsTypeDeclRaw,
        )
      }
    }

    return true
  }

  function processWithDefaults(node: Node): boolean {
    if (!isCallOf(node, WITH_DEFAULTS))
      return false

    if (processDefineProps(node.arguments[0])) {
      if (propsRuntimeDecl) {
        error(
          `${WITH_DEFAULTS} can only be used with type-based `
            + `${DEFINE_PROPS} declaration.`,
          node,
        )
      }
      propsRuntimeDefaults = node.arguments[1]
    }
    else {
      error(
        `${WITH_DEFAULTS}' first argument must be a ${DEFINE_PROPS} call.`,
        node.arguments[0] || node,
      )
    }
    return true
  }

  function processDefineEmits(node: Node): boolean {
    if (!isCallOf(node, DEFINE_EMITS))
      return false

    if (hasDefineEmitCall)
      error(`duplicate ${DEFINE_EMITS}() call`, node)

    hasDefineEmitCall = true
    emitsRuntimeDecl = node.arguments[0]
    if (node.typeParameters) {
      if (emitsRuntimeDecl) {
        error(
          `${DEFINE_EMITS}() cannot accept both type and non-type arguments `
            + 'at the same time. Use one or the other.',
          node,
        )
      }

      emitsTypeDeclRaw = node.typeParameters.params[0]
      emitsTypeDecl = resolveQualifiedType(
        emitsTypeDeclRaw,
        node => node.type === 'TSFunctionType' || node.type === 'TSTypeLiteral',
      ) as TSFunctionType | TSTypeLiteral | TSInterfaceBody | undefined

      if (!emitsTypeDecl) {
        error(
          `type argument passed to ${DEFINE_EMITS}() must be a function type, `
            + 'a literal type with call signatures, or a reference to the above types.',
          emitsTypeDeclRaw,
        )
      }
    }
    return true
  }

  function resolveQualifiedType(
    node: Node,
    qualifier: (node: Node) => boolean,
  ) {
    if (qualifier(node))
      return node

    if (
      node.type === 'TSTypeReference'
      && node.typeName.type === 'Identifier'
    ) {
      const refName = node.typeName.name
      const isQualifiedType = (node: Node): Node | undefined => {
        if (
          node.type === 'TSInterfaceDeclaration'
          && node.id.name === refName
        )
          return node.body

        else if (
          node.type === 'TSTypeAliasDeclaration'
          && node.id.name === refName
          && qualifier(node.typeAnnotation)
        )
          return node.typeAnnotation

        else if (node.type === 'ExportNamedDeclaration' && node.declaration)
          return isQualifiedType(node.declaration)
      }

      for (const node of nodes) {
        const qualified = isQualifiedType(node)
        if (qualified)
          return qualified
      }
    }
  }

  function processDefineExpose(node: Node): boolean {
    if (!isCallOf(node, DEFINE_EXPOSE))
      return false

    if (exposeDecl)
      error(`duplicate ${DEFINE_EXPOSE}() call`, node)

    if (node.arguments.length !== 1)
      error(`${DEFINE_EXPOSE}() requires one argument`, node)

    exposeDecl = node.arguments[0]

    return true
  }

  function processDefineSlots(
    node: Node,
  ): boolean {
    if (!isCallOf(node, DEFINE_SLOTS))
      return false

    if (hasDefineSlotsCall)
      error(`duplicate ${DEFINE_SLOTS}() call`, node)

    hasDefineSlotsCall = true

    if (node.arguments.length > 0)
      error(`${DEFINE_SLOTS}() cannot accept arguments`, node)

    return true
  }

  function genRuntimeProps(props: Record<string, PropTypeData>) {
    const keys = Object.keys(props)
    if (!keys.length)
      return undefined

    // check defaults. If the default object is an object literal with only
    // static properties, we can directly generate more optimzied default
    // decalrations. Otherwise we will have to fallback to runtime merging.
    const hasStaticDefaults = propsRuntimeDefaults
      && propsRuntimeDefaults.type === 'ObjectExpression'
      && propsRuntimeDefaults.properties.every(
        node => node.type === 'ObjectProperty' && !node.computed,
      )

    return t.objectExpression(
      Object.entries(props).map(([key, value]) => {
        const prop = hasStaticDefaults
          ? (propsRuntimeDefaults as ObjectExpression).properties.find((node: any) => node.key.name === key) as ObjectProperty
          : undefined

        if (prop)
          value.required = false

        const entries = Object.entries(value).map(([key, value]) => key === 'type'
          ? t.objectProperty(t.identifier(key), typeof value === 'string' ? t.identifier(value) : t.arrayExpression(value.map((i: any) => t.identifier(i))) as any)
          : t.objectProperty(t.identifier(key), parseExpression(JSON.stringify(value)) as any),
        )

        if (prop)
          entries.push(t.objectProperty(t.identifier('default'), prop.value as any))

        return t.objectProperty(
          t.identifier(key),
          t.objectExpression(entries),
        )
      }),
    )
  }

  function getProps() {
    if (propsRuntimeDecl)
      return propsRuntimeDecl

    if (propsTypeDecl) {
      extractRuntimeProps(propsTypeDecl, typeDeclaredProps, declaredTypes)
      return genRuntimeProps(typeDeclaredProps)
    }
  }

  function throwIfAwait(node: Node) {
    if (node.type === 'AwaitExpression')
      error('top-level await is not supported in Vue 2', node)
  }

  nodes = nodes
    .map((raw: Node) => {
      let node = raw
      if (raw.type === 'ExpressionStatement')
        node = raw.expression

      if (node.type === 'VariableDeclaration' && !node.declare) {
        const total = node.declarations.length
        for (let i = 0; i < total; i++) {
          const decl = node.declarations[i]
          if (decl.init) {
            if (processDefineEmits(decl.init))
              decl.init = t.memberExpression(t.identifier('__ctx'), t.identifier('emit'))
            else if (processDefineSlots(decl.init))
              decl.init = t.memberExpression(t.identifier('__ctx'), t.identifier('slots'))
            else if (processDefineProps(decl.init) || processWithDefaults(decl.init))
              decl.init = t.identifier('__props') as any
            else
              throwIfAwait(decl.init)
          }
        }
      }

      if (processWithDefaults(node) || processDefineEmits(node) || processDefineProps(node) || processDefineExpose(node) || processDefineSlots(node))
        return null

      throwIfAwait(node)

      return raw
    })
    .filter(Boolean) as Statement[]

  return {
    nodes,
    props: getProps(),
    expose: exposeDecl,
  }
}

function isCallOf(
  node: Node | null | undefined,
  test: string | ((id: string) => boolean),
): node is CallExpression {
  return !!(
    node
    && node.type === 'CallExpression'
    && node.callee.type === 'Identifier'
    && (typeof test === 'string'
      ? node.callee.name === test
      : test(node.callee.name))
  )
}

function extractRuntimeProps(
  node: TSTypeLiteral | TSInterfaceBody,
  props: Record<string, PropTypeData>,
  declaredTypes: Record<string, string[]>,
) {
  const members = node.type === 'TSTypeLiteral' ? node.members : node.body
  for (const m of members) {
    if (
      (m.type === 'TSPropertySignature' || m.type === 'TSMethodSignature')
      && m.key.type === 'Identifier'
    ) {
      let type: string[] | undefined
      if (m.type === 'TSMethodSignature') {
        type = ['Function']
      }
      else if (m.typeAnnotation) {
        type = inferRuntimeType(
          m.typeAnnotation.typeAnnotation,
          declaredTypes,
        )
      }
      props[m.key.name] = {
        key: m.key.name,
        required: !m.optional,
        type: type?.length === 1 ? type[0] : type || 'null',
      }
    }
  }
}

function inferRuntimeType(
  node: TSType,
  declaredTypes: Record<string, string[]>,
): string[] {
  switch (node.type) {
    case 'TSStringKeyword':
      return ['String']
    case 'TSNumberKeyword':
      return ['Number']
    case 'TSBooleanKeyword':
      return ['Boolean']
    case 'TSObjectKeyword':
      return ['Object']
    case 'TSTypeLiteral':
      // TODO (nice to have) generate runtime property validation
      return ['Object']
    case 'TSFunctionType':
      return ['Function']
    case 'TSArrayType':
    case 'TSTupleType':
      // TODO (nice to have) generate runtime element type/length checks
      return ['Array']

    case 'TSLiteralType':
      switch (node.literal.type) {
        case 'StringLiteral':
          return ['String']
        case 'BooleanLiteral':
          return ['Boolean']
        case 'NumericLiteral':
        case 'BigIntLiteral':
          return ['Number']
        default:
          return ['null']
      }

    case 'TSTypeReference':
      if (node.typeName.type === 'Identifier') {
        if (declaredTypes[node.typeName.name])
          return declaredTypes[node.typeName.name]

        switch (node.typeName.name) {
          case 'Array':
          case 'Function':
          case 'Object':
          case 'Set':
          case 'Map':
          case 'WeakSet':
          case 'WeakMap':
            return [node.typeName.name]
          case 'Record':
          case 'Partial':
          case 'Readonly':
          case 'Pick':
          case 'Omit':
          case 'Exclude':
          case 'Extract':
          case 'Required':
          case 'InstanceType':
            return ['Object']
        }
      }
      return ['null']

    case 'TSParenthesizedType':
      return inferRuntimeType(node.typeAnnotation, declaredTypes)
    case 'TSUnionType':
      return [
        ...new Set(
          [].concat(
            ...(node.types.map(t => inferRuntimeType(t, declaredTypes)) as any),
          ),
        ),
      ]
    case 'TSIntersectionType':
      return ['Object']

    default:
      return ['null'] // no runtime check
  }
}


================================================
FILE: src/core/options.ts
================================================
import type { ResolvedOptions, ScriptSetupTransformOptions } from '../types'

export function resolveOptions(options: ScriptSetupTransformOptions = {}): ResolvedOptions {
  return Object.assign(
    {},
    {
      sourceMap: true,
      reactivityTransform: false,
      importHelpersFrom: '@vue/composition-api',
      astTransforms: {},
    },
    options,
  )
}


================================================
FILE: src/core/parseSFC.ts
================================================
/* eslint-disable one-var */
/* eslint-disable @typescript-eslint/no-namespace */
import { notNullish, partition } from '@antfu/utils'
import type { Program } from '@babel/types'
import type { ParserPlugin } from '@babel/parser'
import type {
  AttributeNode,
  DirectiveNode,
  ExpressionNode,
  PlainElementNode,
  RootNode,
  TemplateChildNode,
} from '@vue/compiler-core'
import { baseParse } from '@vue/compiler-core'
import { parserOptions } from '@vue/compiler-dom'
import { camelize } from '@vue/shared'
import type {
  ParsedSFC,
  ScriptSetupTransformOptions,
  ScriptTagMeta,
} from '../types'
import { getFileGlobals } from './identifiers'
import { parse } from './babel'
import { exhaustiveCheckReturnUndefined, pascalize } from './utils'

namespace NodeTypes {
  export const ROOT = 0,
    ELEMENT = 1,
    TEXT = 2,
    COMMENT = 3,
    SIMPLE_EXPRESSION = 4,
    INTERPOLATION = 5,
    ATTRIBUTE = 6,
    DIRECTIVE = 7,
    COMPOUND_EXPRESSION = 8,
    IF = 9,
    IF_BRANCH = 10,
    FOR = 11,
    TEXT_CALL = 12,
    VNODE_CALL = 13,
    JS_CALL_EXPRESSION = 14,
    JS_OBJECT_EXPRESSION = 15,
    JS_PROPERTY = 16,
    JS_ARRAY_EXPRESSION = 17,
    JS_FUNCTION_EXPRESSION = 18,
    JS_CONDITIONAL_EXPRESSION = 19,
    JS_CACHE_EXPRESSION = 20,
    JS_BLOCK_STATEMENT = 21,
    JS_TEMPLATE_LITERAL = 22,
    JS_IF_STATEMENT = 23,
    JS_ASSIGNMENT_EXPRESSION = 24,
    JS_SEQUENCE_EXPRESSION = 25,
    JS_RETURN_STATEMENT = 26
}

namespace ElementTypes {
  export const ELEMENT = 0,
    COMPONENT = 1,
    SLOT = 2,
    TEMPLATE = 3
}

const BUILD_IN_DIRECTIVES = new Set([
  'if',
  'else',
  'else-if',
  'for',
  'once',
  'model',
  'on',
  'bind',
  'slot',
  'slot-scope',
  'key',
  'ref',
  'text',
  'html',
  'show',
  'pre',
  'cloak',
  // 'el',
  // 'ref',
])

function getComponents(node: TemplateChildNode): string[] {
  const current
    = node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.COMPONENT
      ? [node.tag]
      : node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.ELEMENT
        ? [node.tag]
        : []

  const children
    = node.type === NodeTypes.IF
      ? node.branches
      : node.type === NodeTypes.ELEMENT
        || node.type === NodeTypes.IF_BRANCH
        || node.type === NodeTypes.FOR
        ? node.children
        : node.type === NodeTypes.TEXT
        || node.type === NodeTypes.COMMENT
        || node.type === NodeTypes.COMPOUND_EXPRESSION
        || node.type === NodeTypes.TEXT_CALL
        || node.type === NodeTypes.INTERPOLATION
          ? []
          : exhaustiveCheckReturnUndefined(node) ?? []

  return [...current, ...children.flatMap(getComponents)]
}

function getDirectiveNames(node: TemplateChildNode): string[] {
  if (node.type === NodeTypes.ELEMENT) {
    const directives = node.props.flatMap(x =>
      x.type === NodeTypes.DIRECTIVE ? [x.name] : [],
    )
    return [...directives, ...node.children.flatMap(getDirectiveNames)]
  }
  else if (node.type === NodeTypes.IF) {
    return node.branches.flatMap(getDirectiveNames)
  }
  else if (node.type === NodeTypes.IF_BRANCH || node.type === NodeTypes.FOR) {
    return node.children.flatMap(getDirectiveNames)
  }
  else if (
    node.type === NodeTypes.INTERPOLATION
    || node.type === NodeTypes.COMPOUND_EXPRESSION
    || node.type === NodeTypes.TEXT
    || node.type === NodeTypes.COMMENT
    || node.type === NodeTypes.TEXT_CALL
  ) {
    return []
  }
  else {
    exhaustiveCheckReturnUndefined(node)
    return []
  }
}

function getFreeVariablesForText(input: string): string[] {
  const inputWithPrefix = input.trimStart()[0] === '{' ? `(${input})` : input
  return getFileGlobals(parse(inputWithPrefix))
}

function getFreeVariablesForPropsNode(
  node: AttributeNode | DirectiveNode,
): string[] {
  if (node.type === NodeTypes.DIRECTIVE) {
    const arg = node.arg === undefined ? [] : getFreeVariablesForNode(node.arg)
    const exp = node.exp === undefined ? [] : getFreeVariablesForNode(node.exp)
    return [...arg, ...exp]
  }
  return []
}

function getFreeVariablesForNode(
  node: TemplateChildNode | ExpressionNode,
): string[] {
  if (node.type === NodeTypes.SIMPLE_EXPRESSION) {
    return node.isStatic ? [] : getFreeVariablesForText(node.content)
  }
  else if (node.type === NodeTypes.COMPOUND_EXPRESSION) {
    return node.children.flatMap(x =>
      typeof x !== 'object' ? [] : getFreeVariablesForNode(x),
    )
  }
  else if (node.type === NodeTypes.INTERPOLATION) {
    return getFreeVariablesForNode(node.content)
  }
  else if (node.type === NodeTypes.ELEMENT) {
    const children = node.children.flatMap(getFreeVariablesForNode)

    const directiveProps = node.props.flatMap(x =>
      x.type === NodeTypes.DIRECTIVE ? [x] : [],
    )
    const attributeProps = node.props.flatMap(x =>
      x.type === NodeTypes.ATTRIBUTE ? [x] : [],
    )

    const refNode = attributeProps.find(
      node => node.name === 'ref' && node.value !== undefined,
    )
    const refIdentifier = refNode?.value?.content

    const vSlotNode = directiveProps.find(node => node.name === 'slot')
    const vSlotArgIdentifiers
      = vSlotNode?.arg === undefined ? [] : getFreeVariablesForNode(vSlotNode.arg)
    // TODO: Variable shadowing
    const vSlotExpVariableShadowingIdentifiers: string[] = []

    const vForNode = directiveProps.find(node => node.name === 'for')
    const vForIdentifiers
      = vForNode?.exp?.type === NodeTypes.SIMPLE_EXPRESSION
        ? getFreeVariablesForText(
          vForNode.exp.content.replace(/^.*\s(?:in|of)\s/, ''),
        )
        : []
    // TODO: Variable shadowing
    const vForExpVariableShadowingIdentifiers: string[] = []

    const props = directiveProps
      .filter(({ name }) => name !== 'slot' && name !== 'for')
      .flatMap(getFreeVariablesForPropsNode)

    const shadowingIdentifiers = new Set([
      ...vSlotExpVariableShadowingIdentifiers,
      ...vForExpVariableShadowingIdentifiers,
    ])
    return [
      ...vSlotArgIdentifiers,
      refIdentifier,
      ...vForIdentifiers,
      ...[...children, ...props].filter(x => !shadowingIdentifiers.has(x)),
    ].filter(notNullish)
  }
  else if (node.type === NodeTypes.FOR) {
    // If we use `baseCompiler`, we need add variable shadowing here
    // But we use `baseParse` now. So this branch will never be reached.
    // `NodeTypes.IF` and `NodeTypes.IF_BRANCH` will never be reached, also.

    // const { keyAlias, valueAlias } = node
    return [node.source, ...node.children].flatMap(getFreeVariablesForNode)
  }
  else if (node.type === NodeTypes.IF) {
    return (node.branches ?? []).flatMap(getFreeVariablesForNode)
  }
  else if (node.type === NodeTypes.IF_BRANCH) {
    return [node.condition, ...node.children]
      .filter(notNullish)
      .flatMap(getFreeVariablesForNode)
  }
  else if (
    node.type === NodeTypes.TEXT
    || node.type === NodeTypes.COMMENT
    || node.type === NodeTypes.TEXT_CALL
  ) {
    return []
  }
  else {
    exhaustiveCheckReturnUndefined(node)
    return []
  }
}

export function findReferencesForSFC(
  templateNode: RootNode | PlainElementNode | undefined,
) {
  const components = templateNode?.children.flatMap(getComponents) ?? []
  const directives = templateNode?.children.flatMap(getDirectiveNames) ?? []
  const identifiers
    = templateNode?.children.flatMap(getFreeVariablesForNode) ?? []

  return {
    components,
    directives,
    identifiers,
  }
}

function getBabelParserOptions(lang: string | null | undefined) {
  lang = lang || 'js'
  const pluginsDict: Record<string, Array<ParserPlugin>> = {
    js: [],
    ts: ['typescript'],
    jsx: ['jsx'],
    tsx: ['jsx', 'typescript'],
  }
  const plugins = pluginsDict[lang]
  if (plugins === undefined)
    throw new SyntaxError(`Unsupported script language: ${lang}`)
  return {
    sourceType: 'module' as const,
    plugins,
  }
}
export async function parseSFC(
  code: string,
  id?: string,
  options?: ScriptSetupTransformOptions,
): Promise<ParsedSFC> {
  const elementChildren = baseParse(code, parserOptions).children.flatMap(x =>
    x.type === NodeTypes.ELEMENT && x.tagType === ElementTypes.ELEMENT
      ? [x]
      : [],
  )
  const templateNode = elementChildren.find(x => x.tag === 'template')

  const [scriptSetupChildNodes, scriptChildNodes] = partition(
    elementChildren.filter(x => x.tag === 'script'),
    x => x.props.some(p => p.type === NodeTypes.ATTRIBUTE && p.name === 'setup'),
  )

  const getScriptTagMeta = (
    n: PlainElementNode | undefined,
    astTransforms: (ast: Program) => Program = x => x,
  ): ScriptTagMeta => {
    if (n === undefined) {
      const content = ''
      const ast = parse(content, {
        sourceType: 'module',
        plugins: [],
      }).program
      return {
        start: 0,
        end: 0,
        contentStart: 0,
        contentEnd: 0,
        content,
        attrs: {},
        found: false,
        ast,
      }
    }
    const attrs = Object.fromEntries(
      n.props.flatMap(x =>
        !(
          x.type === NodeTypes.ATTRIBUTE && typeof x.value?.content === 'string'
        )
          ? []
          : [[x.name, x.value.content]],
      ),
    )
    const content = n.children[0]?.loc.source ?? ''
    const contentStart = n.children[0]?.loc.start.offset ?? 0
    const contentEnd = n.children[0]?.loc.end.offset ?? 0
    const ast = astTransforms(
      parse(content, getBabelParserOptions(attrs.lang)).program,
    )
    return {
      start: n.loc.start.offset,
      end: n.loc.end.offset,
      contentStart,
      contentEnd,
      content,
      attrs,
      found: true,
      ast,
    }
  }
  const scriptSetup = getScriptTagMeta(
    scriptSetupChildNodes[0],
    options?.astTransforms?.scriptSetup,
  )
  const script = getScriptTagMeta(
    scriptChildNodes[0],
    options?.astTransforms?.script,
  )

  if (
    script.found
    && scriptSetup.found
    && scriptSetup.attrs.lang !== script.attrs.lang
  ) {
    throw new SyntaxError(
      '<script setup> language must be the same as <script>',
    )
  }

  const codeOfTemplate
    = templateNode == null
      ? undefined
      : templateNode.props.some(
        p =>
          p.type === NodeTypes.ATTRIBUTE
            && p.name === 'lang'
            && p.value?.type === NodeTypes.TEXT
            && p.value.content === 'pug',
      )
        ? baseParse(
          (await import('pug')).compile(
            templateNode.children.map(x => x.loc.source).join(''),
            {
              filename: id,
            },
          )(),
          parserOptions,
        )
        : templateNode

  const result = codeOfTemplate
    ? findReferencesForSFC(codeOfTemplate)
    : undefined

  return {
    id,
    template: {
      tags: new Set(result?.components),
      components: new Set(result?.components.map(pascalize)),
      directives: new Set(
        result?.directives
          .filter(x => !BUILD_IN_DIRECTIVES.has(x))
          .map(camelize),
      ),
      identifiers: new Set(result?.identifiers),
    },
    scriptSetup,
    script,
    parserOptions: getBabelParserOptions(
      script.attrs.lang ?? scriptSetup.attrs.lang,
    ),
    extraDeclarations: [],
  }
}


================================================
FILE: src/core/transform.ts
================================================
import MagicString from 'magic-string'
import { shouldTransform as shouldTransformRefSugar, transform as transformRef } from '@vue/reactivity-transform'
import type { ResolvedOptions, ScriptSetupTransformOptions, TransformResult } from '../types'
import { parseSFC } from './parseSFC'
import { transformScriptSetup } from './transformScriptSetup'
import { transformSfcRefSugar } from './transformSfcRefSugar'
import { resolveOptions } from './options'

export const scriptSetupRE = /<script\s+(.*\s+)?setup(\s+.*)?\s*>/

export function shouldTransform(code: string, id: string, options?: ScriptSetupTransformOptions): boolean {
  // avoid transforming twice
  if (code.includes('export default __sfc_main'))
    return false
  return (options?.reactivityTransform && shouldTransformRefSugar(code)) || scriptSetupRE.test(code)
}

export async function transform(input: string, id: string, options?: ScriptSetupTransformOptions): Promise<TransformResult> {
  if (!shouldTransform(input, id, options))
    return null
  const resolved = resolveOptions(options)
  if (id.endsWith('.vue') || id.includes('.vue?vue'))
    return await transformVue(input, id, resolved)
  else
    return transformNonVue(input, id, resolved)
}

function transformNonVue(input: string, id: string, options: ResolvedOptions): TransformResult {
  if (options.reactivityTransform && shouldTransformRefSugar(input)) {
    return transformRef(input, {
      filename: id,
      sourceMap: options.sourceMap,
      importHelpersFrom: options.importHelpersFrom,
    }) as any
  }
  return null
}

async function transformVue(input: string, id: string, options: ResolvedOptions): Promise<TransformResult> {
  const s = new MagicString(input)

  const sfc = await parseSFC(input, id)

  if (options.reactivityTransform)
    transformSfcRefSugar(sfc, options)

  const { code } = transformScriptSetup(sfc, options)

  const attributes = {
    ...sfc.script.attrs,
    ...sfc.scriptSetup.attrs,
  }
  delete attributes.setup
  const attr = Object.entries(attributes)
    .map(([key, value]) => value ? `${key}="${value}"` : key)
    .join(' ')

  if (code) {
    const block = `<script ${attr}>\n${code}\n</script>`

    s.remove(sfc.script.start, sfc.script.end)
    if (sfc.scriptSetup.start !== sfc.scriptSetup.end) {
      s.overwrite(
        sfc.scriptSetup.start,
        sfc.scriptSetup.end,
        block,
      )
    }
    else {
      s.prependLeft(0, `${block}\n`)
    }
  }
  return {
    code: s.toString(),
    map: options.sourceMap
      ? s.generateMap({
        source: id,
        includeContent: true,
      }) as any
      : null,
  }
}


================================================
FILE: src/core/transformScriptSetup.ts
================================================
import { capitalize } from '@vue/shared'
import type { Node, ObjectExpression, Statement } from '@babel/types'
import { notNullish, partition, uniq } from '@antfu/utils'
import { parserOptions } from '@vue/compiler-dom'
import type { ParsedSFC, ScriptSetupTransformOptions } from '../types'
import { applyMacros } from './macros'
import { getIdentifierDeclarations } from './identifiers'
import { generate, t } from './babel'
import { pascalize } from './utils'

function isAsyncImport(node: Statement) {
  if (t.isVariableDeclaration(node)) {
    const declaration = node.declarations[0]

    return (
      declaration !== undefined
      && t.isCallExpression(declaration.init)
      && t.isIdentifier(declaration.init.callee)
      && declaration.init.callee.name === 'defineAsyncComponent'
    )
  }

  return false
}

export function transformScriptSetup(
  sfc: ParsedSFC,
  options?: ScriptSetupTransformOptions,
) {
  const { scriptSetup, script, template } = sfc

  const { nodes: body, props, expose } = applyMacros(scriptSetup.ast.body)

  const [hoisted, setupBody] = partition(
    body,
    n =>
      isAsyncImport(n)
      || t.isImportDeclaration(n)
      || t.isExportNamedDeclaration(n)
      || n.type.startsWith('TS'),
  )

  // get all identifiers in `<script setup>` and `<script>`
  const declarationArray = uniq([
    ...getIdentifierDeclarations(hoisted),
    ...getIdentifierDeclarations(setupBody),
    ...getIdentifierDeclarations(script.ast.body),
  ]).filter(notNullish)

  // filter out identifiers that are used in `<template>`
  const returns: ObjectExpression['properties'] = declarationArray
    .filter(i => template.identifiers.has(i))
    .map((i) => {
      const id = t.identifier(i)
      return t.objectProperty(id, id, false, true)
    })

  const nonNativeTags = new Set(
    Array.from(template.tags)
      .filter(tag => !parserOptions.isNativeTag!(tag))
      .map(pascalize),
  )

  const components = Array.from(nonNativeTags)
    .map(
      component =>
        declarationArray.find(declare => declare === component)
        ?? declarationArray.find(declare => pascalize(declare) === component),
    )
    .filter(notNullish)

  const directiveDeclaration = Array.from(template.directives)
    .map((directive) => {
      const identifier = declarationArray.find(
        declaration => declaration === `v${capitalize(directive)}`,
      )
      if (identifier === undefined)
        return undefined

      return { identifier, directive }
    })
    .filter(notNullish)

  // append `<script setup>` imports to `<script>`

  const __sfc = t.identifier('__sfc_main')

  let hasBody = false

  const bodyNodes = script.ast.body.map((node: Node) => {
    // replace `export default` with a temproray variable
    // `const __sfc_main = { ... }`
    if (node.type === 'ExportDefaultDeclaration') {
      hasBody = true
      return t.variableDeclaration('const', [
        t.variableDeclarator(__sfc, node.declaration as any),
      ])
    }
    return node
  })

  let ast = t.program([
    ...sfc.extraDeclarations,
    ...hoisted,
    ...bodyNodes,
  ] as Statement[])

  // inject `const __sfc_main = {}` if `<script>` has default export
  if (!hasBody) {
    ast.body.push(
      t.variableDeclaration('const', [
        t.variableDeclarator(__sfc, t.objectExpression([])),
      ]),
    )
  }

  // inject props function
  // `__sfc_main.props = { ... }`
  if (props) {
    hasBody = true
    ast.body.push(
      t.expressionStatement(
        t.assignmentExpression(
          '=',
          t.memberExpression(__sfc, t.identifier('props')),
          props as any,
        ),
      ) as any,
    )
  }

  // inject setup function
  // `__sfc_main.setup = () => {}`
  if (body.length) {
    hasBody = true
    const returnExpr = expose
      ? t.callExpression(
        t.memberExpression(t.identifier('Object'), t.identifier('assign')),
        [t.objectExpression(returns), expose],
      )
      : t.objectExpression(returns)
    const returnStatement = t.returnStatement(returnExpr)

    ast.body.push(
      t.expressionStatement(
        t.assignmentExpression(
          '=',
          t.memberExpression(__sfc, t.identifier('setup')),
          t.arrowFunctionExpression(
            [t.identifier('__props'), t.identifier('__ctx')],
            t.blockStatement([...setupBody, returnStatement as any]),
          ),
        ),
      ) as any,
    )
  }

  // inject components
  // `__sfc_main.components = Object.assign({ ... }, __sfc_main.components)`
  if (components.length) {
    hasBody = true
    const componentsObject = t.objectExpression(
      components.map((i) => {
        const id = t.identifier(i)
        return t.objectProperty(id, id, false, true)
      }),
    )

    ast.body.push(
      t.expressionStatement(
        t.assignmentExpression(
          '=',
          t.memberExpression(__sfc, t.identifier('components')),
          t.callExpression(
            t.memberExpression(t.identifier('Object'), t.identifier('assign')),
            [
              componentsObject,
              t.memberExpression(__sfc, t.identifier('components')),
            ],
          ),
        ),
      ) as any,
    )
  }

  // inject directives
  // `__sfc_main.directives = Object.assign({ ... }, __sfc_main.directives)`
  if (directiveDeclaration.length) {
    hasBody = true
    const directivesObject = t.objectExpression(
      directiveDeclaration.map(({ directive, identifier }) =>
        t.objectProperty(
          t.identifier(directive),
          t.identifier(identifier),
          false,
          false,
        ),
      ),
    )

    ast.body.push(
      t.expressionStatement(
        t.assignmentExpression(
          '=',
          t.memberExpression(__sfc, t.identifier('directives')),
          t.callExpression(
            t.memberExpression(t.identifier('Object'), t.identifier('assign')),
            [
              directivesObject,
              t.memberExpression(__sfc, t.identifier('directives')),
            ],
          ),
        ),
      ) as any,
    )
  }

  if (!hasBody && !options?.astTransforms) {
    return {
      ast: null,
      code: '',
    }
  }

  // re-export
  // `export default __sfc_main`
  ast.body.push(t.exportDefaultDeclaration(__sfc) as any)

  ast = options?.astTransforms?.post?.(ast, sfc) || ast

  return {
    ast,
    code: generate(ast).code,
  }
}


================================================
FILE: src/core/transformSfcRefSugar.ts
================================================
import { shouldTransform, transformAST } from '@vue/reactivity-transform'
import MagicString from 'magic-string'
import type { ParsedSFC, ResolvedOptions } from '../types'
import { parse, t } from './babel'

export function transformSfcRefSugar(sfc: ParsedSFC, options: ResolvedOptions) {
  const importedHelpers = new Set<string>()

  for (const script of [sfc.script, sfc.scriptSetup]) {
    if (shouldTransform(script.content)) {
      const s = new MagicString(script.content)
      const { importedHelpers: imports } = transformAST(script.ast, s)
      Array.from(imports).forEach(helper => importedHelpers.add(helper))
      script.content = s.toString()
      script.ast = parse(script.content, sfc.parserOptions).program
    }
  }

  if (importedHelpers.size) {
    sfc.extraDeclarations = [
      t.importDeclaration(
        Array.from(importedHelpers).map(i => t.importSpecifier(t.identifier(`_${i}`), t.identifier(i))),
        t.stringLiteral(options.importHelpersFrom),
      ),
    ]
  }
}


================================================
FILE: src/core/utils.ts
================================================
import { camelize, capitalize } from '@vue/shared'

export const pascalize = (str: string) => capitalize(camelize(str))

export const isNotNil = <T>(value: T): value is NonNullable<T> => value != null

export function exhaustiveCheckReturnUndefined(_param: never) {
  return undefined as never
}


================================================
FILE: src/esbuild.ts
================================================
import unplugin from '.'

export default unplugin.esbuild


================================================
FILE: src/index.ts
================================================
import { createUnplugin } from 'unplugin'
import { createFilter } from '@rollup/pluginutils'
import type { PluginOptions } from './types'
import { transform } from './core'

export * from './core'

export const unplugin = createUnplugin<PluginOptions>((options = {}) => {
  const filter = createFilter(
    options.include || (options.reactivityTransform ? [/\.vue$/, /\.vue\?vue/, /\.[jt]sx?$/] : [/\.vue$/, /\.vue\?vue/]),
    options.exclude || [/node_modules/, /\.git/, /\.nuxt/],
  )

  return {
    name: 'unplugin-vue2-script-setup',
    enforce: 'pre',
    transformInclude(id) {
      return filter(id)
    },
    async transform(code, id) {
      try {
        return await transform(code, id, options)
      }
      catch (e: any) {
        this.error(e)
      }
    },
  }
})

export default unplugin


================================================
FILE: src/lib.ts
================================================
export * from './core'


================================================
FILE: src/nuxt.ts
================================================
import defu from 'defu'
import type { PluginOptions } from './types'
import unplugin from '.'

function scriptSetupModule(this: any, inlineOptions: PluginOptions = {}) {
  const options = defu(inlineOptions, this.nuxt.options.scriptSetup)

  // install webpack plugin
  this.extendBuild((config: any) => {
    config.plugins = config.plugins || []
    config.plugins.unshift(unplugin.webpack(options))
  })

  // install vite plugin
  this.nuxt.hook('vite:extend', async (vite: any) => {
    vite.config.plugins = vite.config.plugins || []
    vite.config.plugins.push(unplugin.vite(options))
  })
}

export default scriptSetupModule


================================================
FILE: src/rollup.ts
================================================
import unplugin from '.'

export default unplugin.rollup


================================================
FILE: src/types.ts
================================================
import type { ParserOptions } from '@babel/parser'
import type { Node, Program } from '@babel/types'
import type { FilterPattern } from '@rollup/pluginutils'

export interface ScriptTagMeta {
  start: number
  end: number
  contentStart: number
  contentEnd: number
  content: string
  attrs: Record<string, string>
  found: boolean
  ast: Program
}

export interface ParsedSFC {
  id?: string
  template: {
    /** foo-bar -> FooBar */
    components: Set<string>
    tags: Set<string>
    /** v-foo-bar -> fooBar */
    directives: Set<string>
    identifiers: Set<string>
  }
  scriptSetup: ScriptTagMeta
  script: ScriptTagMeta
  parserOptions: ParserOptions
  extraDeclarations: Node[]
}

export interface ScriptSetupTransformOptions {
  astTransforms?: {
    script?: (ast: Program) => Program
    scriptSetup?: (ast: Program) => Program
    post?: (ast: Program, sfc: ParsedSFC) => Program
  }
  reactivityTransform?: boolean
  importHelpersFrom?: string
  sourceMap?: boolean
}

export interface PluginOptions extends ScriptSetupTransformOptions {
  include?: FilterPattern
  exclude?: FilterPattern
}

export type ResolvedOptions = Required<ScriptSetupTransformOptions>

export interface SourceMap {
  file: string
  mappings: string
  names: string[]
  sources: string[]
  sourcesContent: string[]
  version: number
  toString(): string
  toUrl(): string
}

export type TransformResult = {
  code: string
  readonly map: SourceMap | null
} | null


================================================
FILE: src/vite.ts
================================================
import unplugin from '.'

export default unplugin.vite


================================================
FILE: src/webpack.ts
================================================
import unplugin from '.'

export default unplugin.webpack


================================================
FILE: test/__snapshots__/transform.test.ts.snap
================================================
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`transform > fixtures > playground/src/App.vue 1`] = `
"<script lang=\\"ts\\">
import { defineAsyncComponent } from '@vue/composition-api';
import ButtonTest from './ButtonTest.vue';
import HelloWorld from './HelloWorld.vue';
const AsyncComponent = defineAsyncComponent(() => import('./Async.vue'));
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  function onUpdate(e: any) {
    // eslint-disable-next-line no-console
    console.log(e);
  }
  return {
    onUpdate
  };
};
__sfc_main.components = Object.assign({
  ButtonTest,
  HelloWorld,
  AsyncComponent
}, __sfc_main.components);
export default __sfc_main;
</script>
<template>
  <div>
    <ButtonTest />

    <HelloWorld name=\\"Vue 2\\" @update=\\"onUpdate\\" />

    <AsyncComponent />
  </div>
</template>
"
`;

exports[`transform > fixtures > playground/src/Async.vue 1`] = `
"<template>
  <div>Async Component</div>
</template>
"
`;

exports[`transform > fixtures > playground/src/Bar.vue 1`] = `
"<template>
  <div>Bar</div>
</template>
"
`;

exports[`transform > fixtures > playground/src/ButtonTest.vue 1`] = `
"<script lang=\\"ts\\">
import Button from './Foo.vue';
import button from './Foo.vue';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  return {
    Button,
    button
  };
};
__sfc_main.components = Object.assign({
  Button
}, __sfc_main.components);
export default __sfc_main;
</script>

<template>
  <div>
    <button>{{ Button }}</button>
    <Button>{{ button }}</Button>
  </div>
</template>
"
`;

exports[`transform > fixtures > playground/src/Foo.vue 1`] = `
"<script lang=\\"ts\\">
const __sfc_main = {};
export default __sfc_main;
</script>
<template>
  <div>
    Button Component: <slot></slot>
  </div>
</template>
"
`;

exports[`transform > fixtures > playground/src/HelloWorld.vue 1`] = `
"
<script lang=\\"ts\\">
import { ref as _ref, computed as _computed } from \\"@vue/composition-api\\";
import { watch } from '@vue/composition-api';
import Foo from './Foo.vue';
import Bar from './Bar.vue';
const __sfc_main = {
  name: 'App'
};
__sfc_main.props = {
  msg: {
    key: \\"msg\\",
    required: false,
    type: String,
    default: 'Hello'
  },
  name: {
    key: \\"name\\",
    required: true,
    type: [String, Number]
  }
};
__sfc_main.setup = (__props, __ctx) => {
  const emit = __ctx.emit;
  let count = _ref(0);
  // eslint-disable-next-line prefer-const
  let doubled = _computed(() => count.value * 2);
  function inc() {
    count.value += 1;
  }
  function dec() {
    count.value -= 1;
  }
  const decText = '<b>Dec</b>';
  watch(count.value, value => emit('update', value));
  return {
    Foo,
    Bar,
    count,
    doubled,
    inc,
    dec,
    decText
  };
};
export default __sfc_main;
</script>
<template>
  <div>
    <h3>{{ msg }}, {{ name }}</h3>
    <button @click=\\"inc\\">
      Inc
    </button>
    <div>{{ count }} x 2 = {{ doubled }}</div>
    <button @click=\\"dec()\\" v-html=\\"decText\\" />
    <component :is=\\"count > 2 ? Foo : Bar\\" />
  </div>
</template>
"
`;

exports[`transform > fixtures > playground/src/main.ts 1`] = `
"import Vue from 'vue'
import VueCompositionAPI, { createApp, h } from '@vue/composition-api'
import App from './App.vue'

Vue.use(VueCompositionAPI)

const app = createApp({ render: () => h(App) })

app.mount('#app')
"
`;

exports[`transform > fixtures > playground/src/shims-vue.d.ts 1`] = `
"/// <reference types=\\"unplugin-vue2-script-setup/shims.js\\" />
/// <reference types=\\"unplugin-vue2-script-setup/ref-macros.js\\" />
"
`;

exports[`transform > fixtures > test/fixtures/AsyncImport.vue 1`] = `
"<script lang=\\"ts\\">
import { defineAsyncComponent } from '@vue/composition-api';
const ScriptOnly = defineAsyncComponent(() => import('./ScriptOnly.vue'));
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  return {};
};
__sfc_main.components = Object.assign({
  ScriptOnly
}, __sfc_main.components);
export default __sfc_main;
</script>

<template>
  <ScriptOnly />
</template>
"
`;

exports[`transform > fixtures > test/fixtures/ComponentsDirectives.vue 1`] = `
"<template>
  <div>
    <FooView
      v-if=\\"now > 0\\"
      ref=\\"fooView\\"
      v-foo-bar=\\"message0\\"
      v-d0-demo:foo.a.b=\\"message1\\"
      v-d1-modifiers.a=\\"message2\\"
      v-d2-modifiers-no-value.b.c
      v-d3-arg:click=\\"message3\\"
      v-d4-arg-no-value:click
      v-d5-arg-dynamic:[direction1+direction2.length].c=\\"message4\\"
      v-d6-arg-dynamic-no-value:[direction3]
      v-d6-arg-dynamic-no-value:shouldNotUsed
    >
      <template #[slotName]=\\"{ foo = 1 }\\">
        <div>
          good {{ foo }}
        </div>
      </template>
      <template v-slot:default=\\"bar\\">
        <div>
          good {{ bar }}
        </div>
      </template>
    </FooView>
    <button v-else-if=\\"now === 0\\" :[propNamePrefix+propName]=\\"1\\" @[eventPrefix.value+eventName]=\\"console.log($event)\\"></button>
    <router-view v-else></router-view>
    <img src=\\"https://vuejs.org/images/logo.svg\\">
  </div>
</template>

<script lang=\\"ts\\">
import { ref } from '@vue/runtime-dom';
import FooView from './FooView.vue';
import { vFooBar, vDemo as vD0Demo, vD1Modifiers, vD2ModifiersNoValue, vD3Arg, vD4ArgNoValue, vD5ArgDynamic, vD6ArgDynamicNoValue } from './directive';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const fooView = ref<null | InstanceType<typeof FooView>>(null);
  const message0 = ref('hello');
  const message1 = ref('hello');
  const message2 = ref('hello');
  const message3 = ref('hello');
  const message4 = ref('hello');
  const direction1 = ref('top');
  const direction2 = ref('top');
  const direction3 = ref('top');
  const shouldNotUsed = ref('');
  const propNamePrefix = 'vue-';
  const propName = 'color';
  const eventPrefix = {
    value: 'vue-'
  };
  const eventName = '';
  const console = globalThis.console;
  const now = Date.now();
  const slotName = 'footer';
  return {
    fooView,
    message0,
    message1,
    message2,
    message3,
    message4,
    direction1,
    direction2,
    direction3,
    propNamePrefix,
    propName,
    eventPrefix,
    eventName,
    console,
    now,
    slotName
  };
};
__sfc_main.components = Object.assign({
  FooView
}, __sfc_main.components);
__sfc_main.directives = Object.assign({
  fooBar: vFooBar,
  d0Demo: vD0Demo,
  d1Modifiers: vD1Modifiers,
  d2ModifiersNoValue: vD2ModifiersNoValue,
  d3Arg: vD3Arg,
  d4ArgNoValue: vD4ArgNoValue,
  d5ArgDynamic: vD5ArgDynamic,
  d6ArgDynamicNoValue: vD6ArgDynamicNoValue
}, __sfc_main.directives);
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/ComponentsDirectivesLocal.vue 1`] = `
"
<script lang=\\"ts\\">
import type { ObjectDirective } from '@vue/composition-api';
// enables v-focus in templates
const vFocus: ObjectDirective<HTMLInputElement, null> = {
  inserted: (el, binding, vnode, oldVnode) => {
    el.focus();
  }
};
const __sfc_main = {};
__sfc_main.directives = Object.assign({
  focus: vFocus
}, __sfc_main.directives);
export default __sfc_main;
</script>
<template>
  <input v-focus=\\"null\\">
</template>
"
`;

exports[`transform > fixtures > test/fixtures/ComponentsLocal.vue 1`] = `
"
<script lang=\\"tsx\\">
const HelloComponent = ({
  name
}: {
  name: string;
}) => <span>Hello, {name}</span>;
const __sfc_main = {};
__sfc_main.components = Object.assign({
  HelloComponent
}, __sfc_main.components);
export default __sfc_main;
</script>
<template>
  <HelloComponent name=\\"Evan You\\" />
</template>
"
`;

exports[`transform > fixtures > test/fixtures/DynamicStyle.vue 1`] = `
"<template>
  <div :style=\\"{ color, border: '1px' }\\" />
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const color = computed(() => 'red');
  return {
    color
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/Empty.vue 1`] = `""`;

exports[`transform > fixtures > test/fixtures/Enum.vue 1`] = `
"<template>
  <div>{{ MyEnum }}</div>
</template>

<script lang=\\"ts\\">
enum MyEnum {
  test = 'true',
}
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  return {
    MyEnum
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/HtmlTag.vue 1`] = `
"<script lang=\\"ts\\">
import Enum from './Enum.vue';
import { ref } from '@vue/composition-api';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  let p = \\"hello word\\";
  let Div = ref(\\"hello word\\");
  let h3 = 'test';
  let H3 = '';
  return {
    p,
    Div,
    h3,
    H3
  };
};
__sfc_main.components = Object.assign({
  Enum
}, __sfc_main.components);
export default __sfc_main;
</script>

<template>
  <div>
    <Enum />
    <h3></h3>
    {{ H3 }}
    {{ h3 }}
    {{ Div }}
    <p>{{ p }}</p>
  </div>
</template>
"
`;

exports[`transform > fixtures > test/fixtures/HtmlTag2.vue 1`] = `
"<script lang=\\"ts\\">
import Button from './DynamicStyle.vue';
import button from './DynamicStyle.vue';
import { defineAsyncComponent } from '@vue/composition-api';
const footer = defineAsyncComponent(() => import('./ScriptOnly.vue'));
import { ref } from '@vue/composition-api';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const p = ref(\\"hello word\\");
  return {
    Button,
    button,
    p
  };
};
__sfc_main.components = Object.assign({
  Button
}, __sfc_main.components);
export default __sfc_main;
</script>

<template>
  <div>
    <p>{{ p }}</p>
    <button>{{ Button }}</button>
    <Button>{{ button }}</Button>
    <footer>FOOTER</footer>
  </div>
</template>
"
`;

exports[`transform > fixtures > test/fixtures/JSLongComment.vue 1`] = `
"<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const a = 1;
  ////////////////
  return {
    a
  };
};
export default __sfc_main;
</script>
<template>
  <div>{{ a }}</div>
</template>
"
`;

exports[`transform > fixtures > test/fixtures/Macros.vue 1`] = `
"<template>
  <div @click=\\"emit(props.msg)\\">{{ msg }}</div>
</template>

<script lang=\\"js\\">
const __sfc_main = {};
__sfc_main.props = {
  msg: String
};
__sfc_main.setup = (__props, __ctx) => {
  const props = __props;
  const emit = __ctx.emit;
  return {
    props,
    emit
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosDefineExpose.vue 1`] = `
"<template>
  <div>{{ a }}</div>
  <div>{{ text?.length ?? textLengthDefault }}</div>
</template>

<script lang=\\"ts\\">
import { ref } from '@vue/composition-api';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const a = ref(1);
  const b = 1;
  const text = 'hello';
  const textLengthDefault = 0;
  return Object.assign({
    a,
    text,
    textLengthDefault
  }, {
    b
  });
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosPure.vue 1`] = `
"<template>
  <div>{{ msg }}</div>
</template>

<script >
const __sfc_main = {};
__sfc_main.props = {
  msg: String
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosType.vue 1`] = `
"<template>
  <div @click=\\"emit('update', props.msg)\\">
    {{ msg }}
  </div>
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.props = {
  msg: {
    key: \\"msg\\",
    required: false,
    type: String,
    default: 'Hello'
  },
  value: {
    key: \\"value\\",
    required: true,
    type: [Number, String]
  },
  data: {
    key: \\"data\\",
    required: false,
    type: Object
  }
};
__sfc_main.setup = (__props, __ctx) => {
  const props = __props;
  const emit = __ctx.emit;
  return {
    props,
    emit
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosType2.vue 1`] = `
"<template>
  <div @click=\\"emit(props.msg)\\">
    {{ msg }}
  </div>
</template>

<script lang=\\"ts\\">
export interface Props {
  msg: string;
  value: number | string;
  data?: {
    value: boolean;
  };
  arr?: [number, string, {}];
  any: any;
}
const __sfc_main = {};
__sfc_main.props = {
  msg: {
    key: \\"msg\\",
    required: false,
    type: String,
    default: 'Hello'
  },
  value: {
    key: \\"value\\",
    required: true,
    type: [Number, String]
  },
  data: {
    key: \\"data\\",
    required: false,
    type: Object
  },
  arr: {
    key: \\"arr\\",
    required: false,
    type: Array
  },
  any: {
    key: \\"any\\",
    required: true,
    type: null
  }
};
__sfc_main.setup = (__props, __ctx) => {
  const props = __props;
  const emit = __ctx.emit;
  return {
    props,
    emit
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosType3.vue 1`] = `
"<template>
  <div @click=\\"emit('update', msg);emit('update', msg + value);\\">
    {{ msg }}
  </div>
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.props = {
  msg: {
    key: \\"msg\\",
    required: false,
    type: String,
    default: 'Hello'
  },
  value: {
    key: \\"value\\",
    required: true,
    type: [Number, String]
  },
  data: {
    key: \\"data\\",
    required: false,
    type: Object
  }
};
__sfc_main.setup = (__props, __ctx) => {
  const emit = __ctx.emit;
  const value = 'bar';
  return {
    emit,
    value
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosType4.vue 1`] = `
"<script lang=\\"ts\\">
type Test = number[];
const __sfc_main = {};
__sfc_main.props = {
  test: {
    key: \\"test\\",
    required: false,
    type: null,
    default: () => []
  }
};
__sfc_main.setup = (__props, __ctx) => {
  return {};
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosType5.vue 1`] = `
"<script lang=\\"ts\\">
const __sfc_main = {};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosType6.vue 1`] = `
"<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const slots = __ctx.slots;
  return {
    slots
  };
};
export default __sfc_main;
</script>
<template>
  <template v-if=\\"slots.default\\">
    <slot name=\\"default\\" msg=\\"hello\\"></slot>
  </template>
  <div v-else>
    fallback
  </div>
</template>
"
`;

exports[`transform > fixtures > test/fixtures/MacrosTypeAny.vue 1`] = `
"<template>
  <div>
    {{ value }}
  </div>
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.props = {
  value: {
    key: \\"value\\",
    required: true,
    type: null
  }
};
__sfc_main.setup = (__props, __ctx) => {
  const props = __props;
  return {};
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/Object1.vue 1`] = `
"<template>
  <div>
    {{ data }} {{ title }}
  </div>
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const data = {
    title: 'Template Only'
  };
  return {
    data
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/ObjectDestructure.vue 1`] = `
"<template>
  <div></div>
</template>

<script >
import { toRefs, reactive } from 'vue';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const state = reactive({
    data: 'hello'
  });
  const {
    data
  } = toRefs(state);
  return {};
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/Pug1.vue 1`] = `
"<template lang=\\"pug\\">
.root
  span {{ data }} {{ title }}
  .p-1(@click=\\"foo\\")
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const data = {
    title: 'Template Only'
  };
  function foo() {}
  return {
    data,
    foo
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/RefSugar.ts 1`] = `
"import { ref as _ref, computed as _computed } from '@vue/composition-api'
/* eslint-disable unused-imports/no-unused-vars */
/* eslint-disable prefer-const */
import { ref } from '@vue/composition-api'

let ref1 = (ref('hello'))
ref1.value = 'world'
let ref1Raw = (ref1)

let ref2 = _ref('hello')
ref2.value = 'world'
let ref2Raw = (ref2)

let computed1 = _computed(() => ref2.value += ' str')
let computed1Raw = (computed1)
"
`;

exports[`transform > fixtures > test/fixtures/RefSugar.vue 1`] = `
"<template>
  <div>
    {{ msg }}
    {{ msg2 }}
    {{ a }}
  </div>
</template>



<script lang=\\"ts\\">
import { ref as _ref } from \\"@vue/composition-api\\";
/* eslint-disable prefer-const */
import { defineComponent, ref } from '@vue/composition-api';
const __sfc_main = defineComponent({
  setup() {
    let msg = ref('hello world');
    return {
      msg: msg.value,
      msgRef: msg
    };
  }
});
__sfc_main.setup = (__props, __ctx) => {
  let msg2 = _ref('hello world');
  let a: number;
  a = 2;
  return {
    msg2,
    a
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/RefSugarScriptSetup.vue 1`] = `
"<template>
  <div>
    {{ msg }}
  </div>
</template>

<script lang=\\"ts\\">
import { ref as _ref } from \\"@vue/composition-api\\";
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  /* eslint-disable prefer-const */

  let msg = _ref('hello world');
  return {
    msg
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/ScriptLessThanOrEqualTo.vue 1`] = `
"<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const val: boolean = 1 <= 2;
  return {
    val
  };
};
export default __sfc_main;
</script>

<template>
  <div>{{ val }}</div>
</template>
"
`;

exports[`transform > fixtures > test/fixtures/ScriptOnly.vue 1`] = `
"<script lang=\\"ts\\">
// <script setup> in comment should not be matched
import { defineComponent } from '@vue/composition-api';
const __sfc_main = defineComponent({
  name: 'Hi'
});
export default __sfc_main;
</script>


<!-- <script setup> -->
"
`;

exports[`transform > fixtures > test/fixtures/TemplateOnly.vue 1`] = `
"<template>
  <div>
    <div v-for=\\"(item, index) in items\\" :key=\\"item\\">
      {{ index }}: {{ item }}
    </div>
  </div>
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const items = [{
    name: 'Item 1',
    value: 1
  }, {
    name: 'Item 2',
    value: 2
  }, {
    name: 'Item 3',
    value: 3
  }, {
    name: 'Item 4',
    value: 4
  }];
  return {
    items
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/TemplateOptionalChaining.vue 1`] = `
"<template>
  <div @click=\\"callback?.()\\">
    {{ text?.length ?? textLengthDefault?.[index] }}
    {{ classes?.[0] }}
    {{ arrayObj.data.value[i] }}
  </div>
</template>

<script lang=\\"ts\\">
import { ref } from '@vue/composition-api';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const text = 'hello';
  const textLengthDefault = '';
  const index = ref(0);
  const callback = (undefined as undefined | (() => void));
  const classes = (undefined as undefined | string[]);
  const arrayObj = {
    data: {
      value: [1, 2, 3]
    }
  };
  const i = 0;
  return {
    text,
    textLengthDefault,
    index,
    callback,
    classes,
    arrayObj,
    i
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/VFor.vue 1`] = `
"<template>
  <div>
    <div v-for=\\"(item, index) in items\\" :key=\\"item\\">
      {{ item }}
    </div>
    <div v-for=\\"{ cargo_key, in_of } in items2\\">
      {{ cargo_key }}
    </div>
  </div>
</template>

<script lang=\\"ts\\">
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const items = [{
    name: 'Item 1',
    value: 1
  }, {
    name: 'Item 2',
    value: 2
  }, {
    name: 'Item 3',
    value: 3
  }, {
    name: 'Item 4',
    value: 4
  }];
  const items2 = [{
    cargo_key: 'cargo_key',
    in_of: 'in'
  }];
  const index = 0;
  return {
    items,
    items2
  };
};
export default __sfc_main;
</script>
"
`;

exports[`transform > fixtures > test/fixtures/VariableBinding.vue 1`] = `
"<script lang=\\"ts\\">
/* eslint-disable no-console */
import { reactive } from '@vue/composition-api';
const __sfc_main = {};
__sfc_main.setup = (__props, __ctx) => {
  const state = reactive({
    value: ''
  });
  function showEvent(event: MouseEvent) {
    console.log(event);
  }
  const emit = __ctx.emit;
  return {
    state,
    showEvent,
    emit
  };
};
export default __sfc_main;
</script>
<template>
  <div
    @click=\\"
      state.value = \`x: \${$event.x}\`
      showEvent($event)
      emit('foo')
    \\"
  >
    2333
  </div>
</template>
"
`;


================================================
FILE: test/errors.test.ts
================================================
import { describe, expect, it, vi } from 'vitest'
import { transform as t } from '../src'

describe('errors', () => {
  it('langs', async () => {
    await expect(() =>
      t(`
<script setup>
const a = 1
</script>

<script lang="ts">
export default {}
</script>
`, 'Lang.vue')).rejects.toThrowError('<script setup> language must be the same as <script>')
  })

  it('defineProps', async () => {
    await expect(() =>
      t(`
<script setup>
defineProps()
const a = defineProps()
</script>
`, 'DefineProps.vue'))
      .rejects.toThrowError('duplicate defineProps() call')
  })

  it('top-level await', async () => {
    await expect(() =>
      t(`
<script setup>
defineProps()
await something()
</script>
`, 'TopLevel.vue'))
      .rejects.toThrowError('top-level await is not supported in Vue 2')

    await expect(() =>
      t(`
<script setup>
defineProps()
const {data} = await something()
</script>
`, 'TopLevel.vue'))
      .rejects.toThrowError('top-level await is not supported in Vue 2')
  })

  it('ref sugar', async () => {
    const consoleWarnMock = vi.spyOn(console, 'warn')

    await t(`
<script setup>
defineProps()
const a = async () => {
  await something()
}
</script>
    `, 'App.vue')

    consoleWarnMock.mockRestore()
  })
})


================================================
FILE: test/fixtures/AsyncImport.vue
================================================
<script setup lang="ts">
import { defineAsyncComponent } from '@vue/composition-api'
const ScriptOnly = defineAsyncComponent(() => import('./ScriptOnly.vue'))
</script>

<template>
  <ScriptOnly />
</template>


================================================
FILE: test/fixtures/ComponentsDirectives.vue
================================================
<template>
  <div>
    <FooView
      v-if="now > 0"
      ref="fooView"
      v-foo-bar="message0"
      v-d0-demo:foo.a.b="message1"
      v-d1-modifiers.a="message2"
      v-d2-modifiers-no-value.b.c
      v-d3-arg:click="message3"
      v-d4-arg-no-value:click
      v-d5-arg-dynamic:[direction1+direction2.length].c="message4"
      v-d6-arg-dynamic-no-value:[direction3]
      v-d6-arg-dynamic-no-value:shouldNotUsed
    >
      <template #[slotName]="{ foo = 1 }">
        <div>
          good {{ foo }}
        </div>
      </template>
      <template v-slot:default="bar">
        <div>
          good {{ bar }}
        </div>
      </template>
    </FooView>
    <button v-else-if="now === 0" :[propNamePrefix+propName]="1" @[eventPrefix.value+eventName]="console.log($event)"></button>
    <router-view v-else></router-view>
    <img src="https://vuejs.org/images/logo.svg">
  </div>
</template>

<script setup lang="ts">
import { ref } from '@vue/runtime-dom'
import FooView from './FooView.vue'
import { vFooBar, vDemo as vD0Demo, vD1Modifiers, vD2ModifiersNoValue, vD3Arg, vD4ArgNoValue, vD5ArgDynamic, vD6ArgDynamicNoValue } from './directive'

const fooView = ref<null | InstanceType<typeof FooView>>(null)
const message0 = ref('hello')
const message1 = ref('hello')
const message2 = ref('hello')
const message3 = ref('hello')
const message4 = ref('hello')
const direction1 = ref('top')
const direction2 = ref('top')
const direction3 = ref('top')
const shouldNotUsed = ref('')

const propNamePrefix = 'vue-'
const propName = 'color'
const eventPrefix = { value: 'vue-' }
const eventName = ''

const console = globalThis.console
const now = Date.now()
const slotName = 'footer'
</script>


================================================
FILE: test/fixtures/ComponentsDirectivesLocal.vue
================================================
<script lang="ts">
import type { ObjectDirective } from '@vue/composition-api'
// enables v-focus in templates
const vFocus: ObjectDirective<HTMLInputElement, null> = {
  inserted: (el, binding, vnode, oldVnode) => {
    el.focus()
  },
}
</script>
<script setup lang="ts"></script>
<template>
  <input v-focus="null">
</template>


================================================
FILE: test/fixtures/ComponentsLocal.vue
================================================
<script lang="tsx">
const HelloComponent = ({ name }: { name: string }) => <span>Hello, {name}</span>
</script>
<script setup lang="tsx"></script>
<template>
  <HelloComponent name="Evan You" />
</template>


================================================
FILE: test/fixtures/DynamicStyle.vue
================================================
<template>
  <div :style="{ color, border: '1px' }" />
</template>

<script setup lang="ts">
const color = computed(() => 'red')
</script>


================================================
FILE: test/fixtures/Empty.vue
================================================


================================================
FILE: test/fixtures/Enum.vue
================================================
<template>
  <div>{{ MyEnum }}</div>
</template>

<script setup lang="ts">
enum MyEnum {
  test = 'true',
}
</script>


================================================
FILE: test/fixtures/HtmlTag.vue
================================================
<script setup lang="ts">
import Enum from './Enum.vue'
import { ref } from '@vue/composition-api';

let p = "hello word";
let Div = ref("hello word");
let h3 = 'test'
let H3 = ''
</script>

<template>
  <div>
    <Enum />
    <h3></h3>
    {{ H3 }}
    {{ h3 }}
    {{ Div }}
    <p>{{ p }}</p>
  </div>
</template>


================================================
FILE: test/fixtures/HtmlTag2.vue
================================================
<script setup lang="ts">
import Button from './DynamicStyle.vue';
import button from './DynamicStyle.vue';
import { defineAsyncComponent } from '@vue/composition-api'
const footer = defineAsyncComponent(() => import('./ScriptOnly.vue'))

import { ref } from '@vue/composition-api';

const p = ref("hello word");

</script>

<template>
  <div>
    <p>{{ p }}</p>
    <button>{{ Button }}</button>
    <Button>{{ button }}</Button>
    <footer>FOOTER</footer>
  </div>
</template>


================================================
FILE: test/fixtures/JSLongComment.vue
================================================
<script setup lang="ts">
const a = 1
////////////////
</script>
<template>
  <div>{{ a }}</div>
</template>


================================================
FILE: test/fixtures/Macros.vue
================================================
<template>
  <div @click="emit(props.msg)">{{ msg }}</div>
</template>

<script setup lang="js">
const props = defineProps({
  msg: String,
})

const emit = defineEmits(['msg', 'update'])
</script>


================================================
FILE: test/fixtures/MacrosDefineExpose.vue
================================================
<template>
  <div>{{ a }}</div>
  <div>{{ text?.length ?? textLengthDefault }}</div>
</template>

<script setup lang="ts">
import { ref } from '@vue/composition-api'

const a = ref(1)
const b = 1
const text = 'hello'
const textLengthDefault = 0
defineExpose({ b })
</script>


================================================
FILE: test/fixtures/MacrosPure.vue
================================================
<template>
  <div>{{ msg }}</div>
</template>

<script setup>
defineEmits()
defineProps({
  msg: String,
})
</script>


================================================
FILE: test/fixtures/MacrosType.vue
================================================
<template>
  <div @click="emit('update', props.msg)">
    {{ msg }}
  </div>
</template>

<script setup lang="ts">
const props = withDefaults(
  defineProps<{ msg: string; value: number | string; data?: { value: boolean } }>(),
  { msg: 'Hello' },
)

const emit = defineEmits(['update'])
</script>


================================================
FILE: test/fixtures/MacrosType2.vue
================================================
<template>
  <div @click="emit(props.msg)">
    {{ msg }}
  </div>
</template>

<script setup lang="ts">
export interface Props {
  msg: string
  value: number | string
  data?: { value: boolean }
  arr?: [number, string, {}]
  any: any
}

const props = withDefaults(
  defineProps<Props>(),
  { msg: 'Hello' },
)

const emit = defineEmits<{
  (msg: string): void
  (msg: number): number
}>()
</script>


================================================
FILE: test/fixtures/MacrosType3.vue
================================================
<template>
  <div @click="emit('update', msg);emit('update', msg + value);">
    {{ msg }}
  </div>
</template>

<script setup lang="ts">
withDefaults(
  defineProps<{ msg: string; value: number | string; data?: { value: boolean } }>(),
  { msg: 'Hello' },
)

const emit = defineEmits(['update'])
const value = 'bar'
</script>


================================================
FILE: test/fixtures/MacrosType4.vue
================================================
<script setup lang="ts">
type Test = number[]
withDefaults(
  defineProps<{ test: Test }>(),
  { test: () => [] },
)
</script>


================================================
FILE: test/fixtures/MacrosType5.vue
================================================
<script setup lang="ts">
defineSlots<{
  default: { msg: string }
}>()
</script>


================================================
FILE: test/fixtures/MacrosType6.vue
================================================
<script setup lang="ts">
const slots = defineSlots<{
  default: { msg: string }
}>()
</script>
<template>
  <template v-if="slots.default">
    <slot name="default" msg="hello"></slot>
  </template>
  <div v-else>
    fallback
  </div>
</template>


================================================
FILE: test/fixtures/MacrosTypeAny.vue
================================================
<template>
  <div>
    {{ value }}
  </div>
</template>

<script setup lang="ts">
const props = defineProps<{ value: any }>()
</script>


================================================
FILE: test/fixtures/Object1.vue
================================================
<template>
  <div>
    {{ data }} {{ title }}
  </div>
</template>

<script setup lang="ts">
const data = {
  title: 'Template Only',
}
</script>


================================================
FILE: test/fixtures/ObjectDestructure.vue
================================================
<template>
  <div></div>
</template>

<script setup>
import { toRefs, reactive } from 'vue'
const state = reactive({ data: 'hello' })
const { data } = toRefs(state)
</script>


================================================
FILE: test/fixtures/Pug1.vue
================================================
<template lang="pug">
.root
  span {{ data }} {{ title }}
  .p-1(@click="foo")
</template>

<script setup lang="ts">
const data = {
  title: 'Template Only',
}

function foo() {}
</script>


================================================
FILE: test/fixtures/RefSugar.ts
================================================
/* eslint-disable unused-imports/no-unused-vars */
/* eslint-disable prefer-const */
import { ref } from '@vue/composition-api'

let ref1 = $(ref('hello'))
ref1 = 'world'
let ref1Raw = $$(ref1)

let ref2 = $ref('hello')
ref2 = 'world'
let ref2Raw = $$(ref2)

let computed1 = $computed(() => ref2 += ' str')
let computed1Raw = $$(computed1)


================================================
FILE: test/fixtures/RefSugar.vue
================================================
<template>
  <div>
    {{ msg }}
    {{ msg2 }}
    {{ a }}
  </div>
</template>

<script lang="ts">
/* eslint-disable prefer-const */
import { defineComponent, ref } from '@vue/composition-api'

export default defineComponent({
  setup() {
    let msg = $(ref('hello world'))

    return {
      msg,
      msgRef: $$(msg),
    }
  },
})
</script>

<script setup lang="ts">
let msg2 = $ref('hello world')

let a: number

a = 2
</script>


================================================
FILE: test/fixtures/RefSugarScriptSetup.vue
================================================
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script setup lang="ts">
/* eslint-disable prefer-const */

let msg = $ref('hello world')
</script>


================================================
FILE: test/fixtures/ScriptLessThanOrEqualTo.vue
================================================
<script setup lang="ts">
const val: boolean = 1 <= 2
</script>

<template>
  <div>{{ val }}</div>
</template>


================================================
FILE: test/fixtures/ScriptOnly.vue
================================================
<script lang="ts">
// <script setup> in comment should not be matched
import { defineComponent } from '@vue/composition-api'

export default defineComponent({
  name: 'Hi',
})
</script>

<!-- <script setup> -->


================================================
FILE: test/fixtures/TemplateOnly.vue
================================================
<template>
  <div>
    <div v-for="(item, index) in items" :key="item">
      {{ index }}: {{ item }}
    </div>
  </div>
</template>

<script setup lang="ts">
const items = [
  { name: 'Item 1', value: 1 },
  { name: 'Item 2', value: 2 },
  { name: 'Item 3', value: 3 },
  { name: 'Item 4', value: 4 },
]
</script>


================================================
FILE: test/fixtures/TemplateOptionalChaining.vue
================================================
<template>
  <div @click="callback?.()">
    {{ text?.length ?? textLengthDefault?.[index] }}
    {{ classes?.[0] }}
    {{ arrayObj.data.value[i] }}
  </div>
</template>

<script setup lang="ts">
import { ref } from '@vue/composition-api'
const text = 'hello'
const textLengthDefault = ''
const index = ref(0)

const callback = undefined as undefined | (() => void)
const classes = undefined as undefined | string[]
const arrayObj = { data: { value: [1, 2, 3] } }
const i = 0
</script>


================================================
FILE: test/fixtures/VFor.vue
================================================
<template>
  <div>
    <div v-for="(item, index) in items" :key="item">
      {{ item }}
    </div>
    <div v-for="{ cargo_key, in_of } in items2">
      {{ cargo_key }}
    </div>
  </div>
</template>

<script setup lang="ts">
const items = [
  { name: 'Item 1', value: 1 },
  { name: 'Item 2', value: 2 },
  { name: 'Item 3', value: 3 },
  { name: 'Item 4', value: 4 },
]

const items2 = [
  { cargo_key: 'cargo_key', in_of: 'in' },
]

const index = 0
</script>


================================================
FILE: test/fixtures/VariableBinding.vue
================================================
<script setup lang="ts">
/* eslint-disable no-console */
import { reactive } from '@vue/composition-api'
const state = reactive({ value: '' })
function showEvent(event: MouseEvent) {
  console.log(event)
}
const emit = defineEmits<{
  (event: 'foo'): void
}>()
</script>
<template>
  <div
    @click="
      state.value = `x: ${$event.x}`
      showEvent($event)
      emit('foo')
    "
  >
    2333
  </div>
</template>


================================================
FILE: test/identifiers.test.ts
================================================
/* eslint-disable no-template-curly-in-string */
import { parse } from '@babel/parser'
import { describe, expect, it } from 'vitest'
import { getIdentifierDeclarations, getIdentifierUsages } from '../src/core/identifiers'

describe('identifiers', () => {
  describe('should identifier declarations', () => {
    const cases: [string, string[]][] = [
      ['var a = 1', ['a']],
      ['import { foo, t as bar } from "z"', ['foo', 'bar']],
      ['import foo from "z"', ['foo']],
      ['import Button from \'./DynamicStyle.vue\'', ['Button']],
      ['import button from \'./DynamicStyle.vue\'', ['button']],
      ['import * as foo from "z"', ['foo']],
      ['function foo(bar) {const a = z}', ['foo']],
      ['console.log(foo)', []],
      ['var { data } = toRefs(state)', ['data']],
      ['const { data, ...args } = bar', ['data', 'args']],
      ['const { foo: bar } = bar', ['bar']],
      ['const { foo: { a, b: c, d: { e: [f] } } } = { bar }', ['a', 'c', 'f']],
      ['let [a, b,, ...c] = bar', ['a', 'b', 'c']],
      ['let [a, b, [c, {d}],, ...e] = bar', ['a', 'b', 'c', 'd', 'e']],
      ['class A extends B {}', ['A']],
    ]

    for (const [input, output] of cases) {
      it(input, () => {
        const ast = parse(input, {
          sourceType: 'module',
        })

        expect(new Set(getIdentifierDeclarations(ast.program.body))).toEqual(new Set(output))
      })
    }
  })

  describe('should identifier usages', () => {
    const cases: [string, string[]][] = [
      ['foo', ['foo']],
      ['foo.bar', ['foo']],
      ['foo(bar, console.log, ...args)', ['foo', 'bar', 'console', 'args']],
      ['foo(bar())', ['foo', 'bar']],
      ['for (let x in foo) {}', ['foo']],
      ['for (let [x, idx] of foo) {}', ['foo']],
      ['a + b', ['a', 'b']],
      ['a ? "" : b < c', ['a', 'b', 'c']],
      ['a == b && a === c || d != e', ['a', 'b', 'c', 'd', 'e']],
      ['({ a, b, ...args, [c]: 1, d: e, f: { g } })', ['a', 'b', 'args', 'c', 'e', 'g']],
      ['!a', ['a']],
      ['!!c', ['c']],
      ['[a,b,[c,{d}],...args]', ['a', 'b', 'c', 'd', 'args']],
      ['new Foo(a,[b,,c])', ['Foo', 'a', 'b', 'c']],
      ['new RC.Foo()', ['RC']],
      ['() => foo(bar)', ['foo', 'bar']],
      ['() => { foo() + bar; a }', ['foo', 'bar', 'a']],
      ['(function () { foo() + bar })', ['foo', 'bar']],
      ['function foobar() { return foo() + bar }', ['foo', 'bar']],
      ['`${foo}bar`', ['foo']],
      ['`${foo(zag)}` + bar', ['foo', 'zag', 'bar']],
    ]

    for (const [input, output] of cases) {
      it(input, () => {
        const nodes = parse(input).program.body
        const i = new Set<string>()
        nodes.forEach(node => getIdentifierUsages(node, i))
        expect(i).toEqual(new Set(output))
      })
    }
  })
})


================================================
FILE: test/nativeTag.test.ts
================================================
import { describe, expect, it } from 'vitest'
import { transform } from '../src'

describe('filter native tags as vue components', () => {
  describe('no components output', () => {
    const cases: string[] = [
      `
      <script setup lang="ts">
      import button from './DynamicStyle.vue';
      </script>
      
      <template>
        <button>{{ Button }}</button>
      </template>
      `,
      `
      <script setup lang="ts">
      let p='hello'
      let Div='hello'
      </script>
      
      <template>
        <div>
          <p>{{ p }}</p>
          <Button>{{ Div }}</Button>
        </div>
      </template>
      `,
      `
      <script setup lang="ts">
      let svg='hello'
      </script>
      
      <template>
        <div>
          <p>{{ svg }}</p>
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46">
            <defs>
              <style>
                .cls-1{fill:#231815;}
                @media (prefers-color-scheme: dark) { .cls-1{fill:#ffffff;} }
              </style>
            </defs>
            <path class="cls-1" d="M144.89,89.86c-33.46,0-54.44,14.56-66.14,26.76a86,86,0,0,0-23.69,58.94c0,22.64,8.81,43.48,24.8,58.67,15.7,14.92,36.9,23.14,59.68,23.14,23.81,0,46-8.49,62.49-23.91,17-15.9,26.37-37.93,26.37-62C228.4,120.37,185.94,89.86,144.89,89.86Zm.49,153.67a61.49,61.49,0,0,1-46.45-20.4c-12.33-13.76-18.85-32.64-18.85-54.62,0-20.7,6.07-37.67,17.57-49.07,10.11-10,24.39-15.62,40.19-15.74,19,0,35.22,6.56,46.76,19,12.6,13.58,19.27,34,19.27,58.95C203.87,224.39,174.49,243.53,145.38,243.53Z"/>
            <polygon class="cls-1" points="198.75 74.96 179.45 74.96 142.09 37.83 104.51 74.96 86.14 74.96 138.09 24.25 146.81 24.25 198.75 74.96"/>
          </svg>
        </div>
      </template>
      `,
    ]

    for (const input of cases) {
      it(input, async () => {
        const result = await transform(input, 'Lang.vue', { reactivityTransform: true })
        expect(result?.code.includes('__sfc_main.components')).toEqual(false)
      })
    }
  })

  it('capitalized native tags as components', async () => {
    const input = `
    <script setup lang="ts">
    import Button from './DynamicStyle.vue';
    </script>
    
    <template>
      <Button>{{ Button }}</Button>
    </template>
    `
    const result = await transform(input, 'Lang.vue', { reactivityTransform: true })
    expect(result?.code.includes('__sfc_main.components = Object.assign({\n  Button\n}, __sfc_main.components);')).toEqual(true)
  })

  it('keep non-native components', async () => {
    const input = `
    <script setup lang="ts">
    import Button from './DynamicStyle.vue';
    import DynamicStyle from './DynamicStyle.vue';
    let p='hello'
    </script>
    
    <template>
      <dynamic-style/>
      <p>{{ p }}</p>
      <button>{{ Button }}</button>
    </template>
    `
    const result = await transform(input, 'Lang.vue', { reactivityTransform: true })
    expect(result?.code.includes('__sfc_main.components = Object.assign({\n  DynamicStyle\n}, __sfc_main.components);')).toEqual(true)
  })
})


================================================
FILE: test/transform.test.ts
================================================
import { resolve } from 'node:path'
import { promises as fs } from 'node:fs'
import fg from 'fast-glob'
import { describe, expect, it } from 'vitest'
import { transform } from '../src'

describe('transform', () => {
  describe('fixtures', () => {
    const root = resolve(__dirname, '..')
    const files = fg.sync([
      'test/fixtures/*.{vue,js,ts}',
      'playground/src/*.{vue,js,ts}',
    ], {
      cwd: root,
      onlyFiles: true,
    })

    for (const file of files) {
      it(file.replace(/\\/g, '/'), async () => {
        const fixture = await fs.readFile(resolve(root, file), 'utf-8')
        const result = (await transform(fixture, file, { reactivityTransform: true }))?.code || fixture
        expect(result).toMatchSnapshot()

        const result2 = (await transform(result, file, { reactivityTransform: true }))?.code || result
        expect(result).toEqual(result2)
      })
    }
  })
})


================================================
FILE: test/transform_filter.test.ts
================================================
import { } from 'node:test'
import { describe, expect, it } from 'vitest'
import { scriptSetupRE } from '../src/core'

describe('transform filter', () => {
  describe('look for what needs to be converted by regular ', () => {
    const cases: string[] = [
      `<script  lang="tsx"
      setup>
      import HelloWorld from './HelloWorld.vue'
      </setup>`,
      '<script  lang="ts" setup>',
      `<script 
       lang="ts"
        setup>
        import HelloWorld from './HelloWorld.vue'
        </script>`,
        `<script 
        setup>
        import HelloWorld from './HelloWorld.vue'
        </script>`,
        `<script setup>
        import HelloWorld from './HelloWorld.vue'
        </script>`,
        `<script setup lang="tsx"      >
        import HelloWorld from './HelloWorld.vue'
        </script>
        `,
        `<script setup 
        lang="ts">
        import HelloWorld from './HelloWorld.vue'
        </script>
        `,
        `<script 
        setup 
                lang="ts">
        import HelloWorld from './HelloWorld.vue'
        </script>
                `,
       `<script setup 
                lang="ts">
         import HelloWorld from './HelloWorld.vue'
        </script>`,
    ]

    for (const input of cases) {
      it(input, () => {
        expect(scriptSetupRE.test(input)).toEqual(true)
      })
    }
  })

  describe('filter what is not needed by regular ', () => {
    const cases: string[] = [
      `<scriptlang="ts"
      setup>
      import HelloWorld from './HelloWorld.vue'
      </script>
      `,
      `<script lang="ts">
      import HelloWorld from './HelloWorld.vue'
      </script>`,
      `<script>
      import HelloWorld from './HelloWorld.vue'
      </script>
      `,
    ]

    for (const input of cases) {
      it(input, () => {
        expect(scriptSetupRE.test(input)).toEqual(false)
      })
    }
  })
})


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es2017",
    "module": "esnext",
    "lib": ["esnext", "dom"],
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "jsx": "preserve",
    "strictNullChecks": true,
    "isolatedModules": true,
    "resolveJsonModule": true
  }
}


================================================
FILE: types.d.ts
================================================
export { default } from './dist/types'


================================================
FILE: vite.d.ts
================================================
export { default } from './dist/vite'


================================================
FILE: webpack.d.ts
================================================
export { default } from './dist/webpack'
Download .txt
gitextract_7eas0mg5/

├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .npmrc
├── .tazerc.json
├── LICENSE
├── README.md
├── esbuild.d.ts
├── examples/
│   └── vue-cli/
│       ├── .npmrc
│       ├── babel.config.js
│       ├── package.json
│       ├── public/
│       │   └── index.html
│       ├── src/
│       │   ├── App.vue
│       │   ├── components/
│       │   │   └── HelloWorld.vue
│       │   ├── main.ts
│       │   └── shims-vue.d.ts
│       ├── tsconfig.json
│       └── vue.config.cjs
├── index.d.ts
├── jest.js
├── nuxt.d.ts
├── package.json
├── playground/
│   ├── index.html
│   ├── package.json
│   ├── src/
│   │   ├── App.vue
│   │   ├── Async.vue
│   │   ├── Bar.vue
│   │   ├── ButtonTest.vue
│   │   ├── Foo.vue
│   │   ├── HelloWorld.vue
│   │   ├── main.ts
│   │   └── shims-vue.d.ts
│   ├── tsconfig.json
│   └── vite.config.ts
├── pnpm-workspace.yaml
├── ref-macros.d.ts
├── rollup.config.mjs
├── rollup.d.ts
├── scripts/
│   └── postbuild.ts
├── shims.d.ts
├── src/
│   ├── core/
│   │   ├── babel.ts
│   │   ├── identifiers.ts
│   │   ├── index.ts
│   │   ├── macros.ts
│   │   ├── options.ts
│   │   ├── parseSFC.ts
│   │   ├── transform.ts
│   │   ├── transformScriptSetup.ts
│   │   ├── transformSfcRefSugar.ts
│   │   └── utils.ts
│   ├── esbuild.ts
│   ├── index.ts
│   ├── lib.ts
│   ├── nuxt.ts
│   ├── rollup.ts
│   ├── types.ts
│   ├── vite.ts
│   └── webpack.ts
├── test/
│   ├── __snapshots__/
│   │   └── transform.test.ts.snap
│   ├── errors.test.ts
│   ├── fixtures/
│   │   ├── AsyncImport.vue
│   │   ├── ComponentsDirectives.vue
│   │   ├── ComponentsDirectivesLocal.vue
│   │   ├── ComponentsLocal.vue
│   │   ├── DynamicStyle.vue
│   │   ├── Empty.vue
│   │   ├── Enum.vue
│   │   ├── HtmlTag.vue
│   │   ├── HtmlTag2.vue
│   │   ├── JSLongComment.vue
│   │   ├── Macros.vue
│   │   ├── MacrosDefineExpose.vue
│   │   ├── MacrosPure.vue
│   │   ├── MacrosType.vue
│   │   ├── MacrosType2.vue
│   │   ├── MacrosType3.vue
│   │   ├── MacrosType4.vue
│   │   ├── MacrosType5.vue
│   │   ├── MacrosType6.vue
│   │   ├── MacrosTypeAny.vue
│   │   ├── Object1.vue
│   │   ├── ObjectDestructure.vue
│   │   ├── Pug1.vue
│   │   ├── RefSugar.ts
│   │   ├── RefSugar.vue
│   │   ├── RefSugarScriptSetup.vue
│   │   ├── ScriptLessThanOrEqualTo.vue
│   │   ├── ScriptOnly.vue
│   │   ├── TemplateOnly.vue
│   │   ├── TemplateOptionalChaining.vue
│   │   ├── VFor.vue
│   │   └── VariableBinding.vue
│   ├── identifiers.test.ts
│   ├── nativeTag.test.ts
│   ├── transform.test.ts
│   └── transform_filter.test.ts
├── tsconfig.json
├── types.d.ts
├── vite.d.ts
└── webpack.d.ts
Download .txt
SYMBOL INDEX (50 symbols across 16 files)

FILE: examples/vue-cli/vue.config.cjs
  method chainWebpack (line 13) | chainWebpack(config) {

FILE: jest.js
  function requireVueJest (line 3) | function requireVueJest() {
  method process (line 17) | async process(source, filename, ...args) {

FILE: ref-macros.d.ts
  type RefValue (line 11) | type RefValue<T> = T & { [RefMarker]?: any }
  type ComputedRefValue (line 14) | type ComputedRefValue<T> = T & { [ComputedRefMarker]?: any }
  type WritableComputedRefValue (line 17) | type WritableComputedRefValue<T> = T & { [WritableComputedRefMarker]?: a...
  type ToRawRefs (line 19) | type ToRawRefs<T extends object> = {

FILE: rollup.config.mjs
  method onwarn (line 52) | onwarn({ code, message }) {

FILE: scripts/postbuild.ts
  function run (line 5) | async function run() {

FILE: src/core/identifiers.ts
  function getIdentifierDeclarations (line 12) | function getIdentifierDeclarations(nodes: Statement[]) {
  function getIdentifierUsages (line 39) | function getIdentifierUsages(node?: Expression | TSType | SpreadElement ...
  function getFileGlobals (line 110) | function getFileGlobals(result: ParseResult<File>) {

FILE: src/core/macros.ts
  constant DEFINE_PROPS (line 17) | const DEFINE_PROPS = 'defineProps'
  constant DEFINE_EMITS (line 18) | const DEFINE_EMITS = 'defineEmits'
  constant DEFINE_EXPOSE (line 19) | const DEFINE_EXPOSE = 'defineExpose'
  constant WITH_DEFAULTS (line 20) | const WITH_DEFAULTS = 'withDefaults'
  constant DEFINE_SLOTS (line 21) | const DEFINE_SLOTS = 'defineSlots'
  type PropTypeData (line 23) | interface PropTypeData {
  function applyMacros (line 29) | function applyMacros(nodes: Statement[]) {
  function isCallOf (line 319) | function isCallOf(
  function extractRuntimeProps (line 333) | function extractRuntimeProps(
  function inferRuntimeType (line 363) | function inferRuntimeType(

FILE: src/core/options.ts
  function resolveOptions (line 3) | function resolveOptions(options: ScriptSetupTransformOptions = {}): Reso...

FILE: src/core/parseSFC.ts
  constant BUILD_IN_DIRECTIVES (line 63) | const BUILD_IN_DIRECTIVES = new Set([
  function getComponents (line 85) | function getComponents(node: TemplateChildNode): string[] {
  function getDirectiveNames (line 111) | function getDirectiveNames(node: TemplateChildNode): string[] {
  function getFreeVariablesForText (line 139) | function getFreeVariablesForText(input: string): string[] {
  function getFreeVariablesForPropsNode (line 144) | function getFreeVariablesForPropsNode(
  function getFreeVariablesForNode (line 155) | function getFreeVariablesForNode(
  function findReferencesForSFC (line 244) | function findReferencesForSFC(
  function getBabelParserOptions (line 259) | function getBabelParserOptions(lang: string | null | undefined) {
  function parseSFC (line 275) | async function parseSFC(

FILE: src/core/transform.ts
  function shouldTransform (line 11) | function shouldTransform(code: string, id: string, options?: ScriptSetup...
  function transform (line 18) | async function transform(input: string, id: string, options?: ScriptSetu...
  function transformNonVue (line 28) | function transformNonVue(input: string, id: string, options: ResolvedOpt...
  function transformVue (line 39) | async function transformVue(input: string, id: string, options: Resolved...

FILE: src/core/transformScriptSetup.ts
  function isAsyncImport (line 11) | function isAsyncImport(node: Statement) {
  function transformScriptSetup (line 26) | function transformScriptSetup(

FILE: src/core/transformSfcRefSugar.ts
  function transformSfcRefSugar (line 6) | function transformSfcRefSugar(sfc: ParsedSFC, options: ResolvedOptions) {

FILE: src/core/utils.ts
  function exhaustiveCheckReturnUndefined (line 7) | function exhaustiveCheckReturnUndefined(_param: never) {

FILE: src/index.ts
  method transformInclude (line 17) | transformInclude(id) {
  method transform (line 20) | async transform(code, id) {

FILE: src/nuxt.ts
  function scriptSetupModule (line 5) | function scriptSetupModule(this: any, inlineOptions: PluginOptions = {}) {

FILE: src/types.ts
  type ScriptTagMeta (line 5) | interface ScriptTagMeta {
  type ParsedSFC (line 16) | interface ParsedSFC {
  type ScriptSetupTransformOptions (line 32) | interface ScriptSetupTransformOptions {
  type PluginOptions (line 43) | interface PluginOptions extends ScriptSetupTransformOptions {
  type ResolvedOptions (line 48) | type ResolvedOptions = Required<ScriptSetupTransformOptions>
  type SourceMap (line 50) | interface SourceMap {
  type TransformResult (line 61) | type TransformResult = {
Condensed preview — 103 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (124K chars).
[
  {
    "path": ".eslintignore",
    "chars": 24,
    "preview": "dist\nnode_modules\n*.vue\n"
  },
  {
    "path": ".eslintrc.json",
    "chars": 26,
    "preview": "{\n  \"extends\": \"@antfu\"\n}\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 16,
    "preview": "github: [antfu]\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 690,
    "preview": "name: Release\n\non:\n  push:\n    tags:\n      - 'v*'\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    permissions:\n      co"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 868,
    "preview": "name: Test\n\non:\n  push:\n    branches:\n      - main\n      - master\n\n  pull_request:\n    branches:\n      - main\n      - ma"
  },
  {
    "path": ".gitignore",
    "chars": 1194,
    "preview": "# Created by .ignore support plugin (hsz.mobi)\n### Node template\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-e"
  },
  {
    "path": ".npmrc",
    "chars": 64,
    "preview": "ignore-workspace-root-check=true\nstrict-peer-dependencies=false\n"
  },
  {
    "path": ".tazerc.json",
    "chars": 52,
    "preview": "{\n  \"exclude\": [\n    \"vue\",\n    \"htmlparser2\"\n  ]\n}\n"
  },
  {
    "path": "LICENSE",
    "chars": 1094,
    "preview": "MIT License\n\nCopyright (c) 2021 Anthony Fu <https://github.com/antfu>\n\nPermission is hereby granted, free of charge, to "
  },
  {
    "path": "README.md",
    "chars": 7067,
    "preview": "# unplugin-vue2-script-setup\n\n[![NPM version](https://img.shields.io/npm/v/unplugin-vue2-script-setup?color=a1b858&label"
  },
  {
    "path": "esbuild.d.ts",
    "chars": 41,
    "preview": "export { default } from './dist/esbuild'\n"
  },
  {
    "path": "examples/vue-cli/.npmrc",
    "chars": 22,
    "preview": "shamefully-hoist=true\n"
  },
  {
    "path": "examples/vue-cli/babel.config.js",
    "chars": 75,
    "preview": "module.exports = {\n  presets: [\n    '@vue/cli-plugin-babel/preset',\n  ],\n}\n"
  },
  {
    "path": "examples/vue-cli/package.json",
    "chars": 606,
    "preview": "{\n  \"name\": \"vue-cli\",\n  \"private\": true,\n  \"scripts\": {\n    \"type-check\": \"vue-tsc --noEmit\",\n    \"dev\": \"vue-cli-servi"
  },
  {
    "path": "examples/vue-cli/public/index.html",
    "chars": 555,
    "preview": "<!DOCTYPE html>\n<html lang=\"\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "examples/vue-cli/src/App.vue",
    "chars": 405,
    "preview": "<script setup lang=\"ts\">\nimport HelloWorld from './components/HelloWorld.vue'\n</script>\n<template>\n  <div id=\"app\">\n    "
  },
  {
    "path": "examples/vue-cli/src/components/HelloWorld.vue",
    "chars": 1799,
    "preview": "<script setup lang=\"ts\">\ndefineProps<{\n  msg: string\n}>()\n</script>\n<template>\n  <div class=\"hello\">\n    <h1>{{ msg }}</"
  },
  {
    "path": "examples/vue-cli/src/main.ts",
    "chars": 253,
    "preview": "import Vue from 'vue'\nimport VueCompositionAPI, { createApp, h } from '@vue/composition-api'\nimport App from './App.vue'"
  },
  {
    "path": "examples/vue-cli/src/shims-vue.d.ts",
    "chars": 62,
    "preview": "/// <reference types=\"unplugin-vue2-script-setup/shims.js\" />\n"
  },
  {
    "path": "examples/vue-cli/tsconfig.json",
    "chars": 529,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"jsx\": \"preserve\",\n    "
  },
  {
    "path": "examples/vue-cli/vue.config.cjs",
    "chars": 728,
    "preview": "const { defineConfig } = require('@vue/cli-service')\nconst ScriptSetup = require('unplugin-vue2-script-setup/webpack').d"
  },
  {
    "path": "index.d.ts",
    "chars": 39,
    "preview": "export { default } from './dist/index'\n"
  },
  {
    "path": "jest.js",
    "chars": 634,
    "preview": "const { transform } = require('./dist/index')\n\nfunction requireVueJest() {\n  const names = ['@vue/vue2-jest', 'vue-jest'"
  },
  {
    "path": "nuxt.d.ts",
    "chars": 38,
    "preview": "export { default } from './dist/nuxt'\n"
  },
  {
    "path": "package.json",
    "chars": 3434,
    "preview": "{\n  \"name\": \"unplugin-vue2-script-setup\",\n  \"version\": \"0.11.4\",\n  \"packageManager\": \"pnpm@8.6.11\",\n  \"description\": \"Br"
  },
  {
    "path": "playground/index.html",
    "chars": 314,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <link rel=\"icon\" href=\"/favicon.ico\" />\n  <meta name="
  },
  {
    "path": "playground/package.json",
    "chars": 339,
    "preview": "{\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"vite --open\",\n    \"build\": \"vite build\"\n  },\n  \"dependencies\": {\n    \"@v"
  },
  {
    "path": "playground/src/App.vue",
    "chars": 478,
    "preview": "<script setup lang=\"ts\">\nimport { defineAsyncComponent } from '@vue/composition-api'\nimport ButtonTest from './ButtonTes"
  },
  {
    "path": "playground/src/Async.vue",
    "chars": 52,
    "preview": "<template>\n  <div>Async Component</div>\n</template>\n"
  },
  {
    "path": "playground/src/Bar.vue",
    "chars": 40,
    "preview": "<template>\n  <div>Bar</div>\n</template>\n"
  },
  {
    "path": "playground/src/ButtonTest.vue",
    "chars": 208,
    "preview": "<script setup lang=\"ts\">\nimport Button from './Foo.vue';\nimport button from './Foo.vue';\n</script>\n\n<template>\n  <div>\n "
  },
  {
    "path": "playground/src/Foo.vue",
    "chars": 112,
    "preview": "<script setup lang=\"ts\">\n\n</script>\n<template>\n  <div>\n    Button Component: <slot></slot>\n  </div>\n</template>\n"
  },
  {
    "path": "playground/src/HelloWorld.vue",
    "chars": 902,
    "preview": "<script lang=\"ts\">\n/* eslint-disable import/first */\nexport default {\n  name: 'App',\n}\n</script>\n<script setup lang=\"ts\""
  },
  {
    "path": "playground/src/main.ts",
    "chars": 217,
    "preview": "import Vue from 'vue'\nimport VueCompositionAPI, { createApp, h } from '@vue/composition-api'\nimport App from './App.vue'"
  },
  {
    "path": "playground/src/shims-vue.d.ts",
    "chars": 129,
    "preview": "/// <reference types=\"unplugin-vue2-script-setup/shims.js\" />\n/// <reference types=\"unplugin-vue2-script-setup/ref-macro"
  },
  {
    "path": "playground/tsconfig.json",
    "chars": 545,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"jsx\": \"preserve\",\n    "
  },
  {
    "path": "playground/vite.config.ts",
    "chars": 344,
    "preview": "import { defineConfig } from 'vite'\nimport { createVuePlugin as Vue2 } from 'vite-plugin-vue2'\nimport Inspect from 'vite"
  },
  {
    "path": "pnpm-workspace.yaml",
    "chars": 41,
    "preview": "- packages\n  - playground\n  - examples/*\n"
  },
  {
    "path": "ref-macros.d.ts",
    "chars": 2266,
    "preview": "import type {\n  ComputedRef,\n  Ref,\n  ShallowUnwrapRef,\n  UnwrapRef,\n  WritableComputedOptions,\n  WritableComputedRef,\n}"
  },
  {
    "path": "rollup.config.mjs",
    "chars": 1796,
    "preview": "// @ts-check\nimport * as fs from 'node:fs'\nimport ts from 'rollup-plugin-esbuild'\nimport dts from 'rollup-plugin-dts'\nim"
  },
  {
    "path": "rollup.d.ts",
    "chars": 40,
    "preview": "export { default } from './dist/rollup'\n"
  },
  {
    "path": "scripts/postbuild.ts",
    "chars": 711,
    "preview": "import { basename, resolve } from 'node:path'\nimport { promises as fs } from 'node:fs'\nimport fg from 'fast-glob'\n\nasync"
  },
  {
    "path": "shims.d.ts",
    "chars": 306,
    "preview": "// workaround for Volar to infer the ref type in <template>\n// https://github.com/johnsoncodehk/volar/issues/404\ndeclare"
  },
  {
    "path": "src/core/babel.ts",
    "chars": 471,
    "preview": "import * as babel from '@babel/core'\nimport { parse, parseExpression } from '@babel/parser'\nimport g from '@babel/genera"
  },
  {
    "path": "src/core/identifiers.ts",
    "chars": 4568,
    "preview": "import type {\n  Expression,\n  File,\n  PrivateName,\n  SpreadElement,\n  Statement,\n  TSType,\n} from '@babel/types'\nimport "
  },
  {
    "path": "src/core/index.ts",
    "chars": 92,
    "preview": "export * from './transform'\nexport * from './transformScriptSetup'\nexport * from '../types'\n"
  },
  {
    "path": "src/core/macros.ts",
    "chars": 12283,
    "preview": "// modified from https://github.com/vuejs/vue-next/blob/main/packages/compiler-sfc/src/compileScript.ts\n\nimport type {\n "
  },
  {
    "path": "src/core/options.ts",
    "chars": 366,
    "preview": "import type { ResolvedOptions, ScriptSetupTransformOptions } from '../types'\n\nexport function resolveOptions(options: Sc"
  },
  {
    "path": "src/core/parseSFC.ts",
    "chars": 11182,
    "preview": "/* eslint-disable one-var */\n/* eslint-disable @typescript-eslint/no-namespace */\nimport { notNullish, partition } from "
  },
  {
    "path": "src/core/transform.ts",
    "chars": 2624,
    "preview": "import MagicString from 'magic-string'\nimport { shouldTransform as shouldTransformRefSugar, transform as transformRef } "
  },
  {
    "path": "src/core/transformScriptSetup.ts",
    "chars": 6398,
    "preview": "import { capitalize } from '@vue/shared'\nimport type { Node, ObjectExpression, Statement } from '@babel/types'\nimport { "
  },
  {
    "path": "src/core/transformSfcRefSugar.ts",
    "chars": 1005,
    "preview": "import { shouldTransform, transformAST } from '@vue/reactivity-transform'\nimport MagicString from 'magic-string'\nimport "
  },
  {
    "path": "src/core/utils.ts",
    "chars": 296,
    "preview": "import { camelize, capitalize } from '@vue/shared'\n\nexport const pascalize = (str: string) => capitalize(camelize(str))\n"
  },
  {
    "path": "src/esbuild.ts",
    "chars": 58,
    "preview": "import unplugin from '.'\n\nexport default unplugin.esbuild\n"
  },
  {
    "path": "src/index.ts",
    "chars": 813,
    "preview": "import { createUnplugin } from 'unplugin'\nimport { createFilter } from '@rollup/pluginutils'\nimport type { PluginOptions"
  },
  {
    "path": "src/lib.ts",
    "chars": 23,
    "preview": "export * from './core'\n"
  },
  {
    "path": "src/nuxt.ts",
    "chars": 634,
    "preview": "import defu from 'defu'\nimport type { PluginOptions } from './types'\nimport unplugin from '.'\n\nfunction scriptSetupModul"
  },
  {
    "path": "src/rollup.ts",
    "chars": 57,
    "preview": "import unplugin from '.'\n\nexport default unplugin.rollup\n"
  },
  {
    "path": "src/types.ts",
    "chars": 1457,
    "preview": "import type { ParserOptions } from '@babel/parser'\nimport type { Node, Program } from '@babel/types'\nimport type { Filte"
  },
  {
    "path": "src/vite.ts",
    "chars": 55,
    "preview": "import unplugin from '.'\n\nexport default unplugin.vite\n"
  },
  {
    "path": "src/webpack.ts",
    "chars": 58,
    "preview": "import unplugin from '.'\n\nexport default unplugin.webpack\n"
  },
  {
    "path": "test/__snapshots__/transform.test.ts.snap",
    "chars": 20890,
    "preview": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`transform > fixtures > playground/src/App.vue 1`"
  },
  {
    "path": "test/errors.test.ts",
    "chars": 1255,
    "preview": "import { describe, expect, it, vi } from 'vitest'\nimport { transform as t } from '../src'\n\ndescribe('errors', () => {\n  "
  },
  {
    "path": "test/fixtures/AsyncImport.vue",
    "chars": 210,
    "preview": "<script setup lang=\"ts\">\nimport { defineAsyncComponent } from '@vue/composition-api'\nconst ScriptOnly = defineAsyncCompo"
  },
  {
    "path": "test/fixtures/ComponentsDirectives.vue",
    "chars": 1703,
    "preview": "<template>\n  <div>\n    <FooView\n      v-if=\"now > 0\"\n      ref=\"fooView\"\n      v-foo-bar=\"message0\"\n      v-d0-demo:foo."
  },
  {
    "path": "test/fixtures/ComponentsDirectivesLocal.vue",
    "chars": 331,
    "preview": "<script lang=\"ts\">\nimport type { ObjectDirective } from '@vue/composition-api'\n// enables v-focus in templates\nconst vFo"
  },
  {
    "path": "test/fixtures/ComponentsLocal.vue",
    "chars": 207,
    "preview": "<script lang=\"tsx\">\nconst HelloComponent = ({ name }: { name: string }) => <span>Hello, {name}</span>\n</script>\n<script "
  },
  {
    "path": "test/fixtures/DynamicStyle.vue",
    "chars": 139,
    "preview": "<template>\n  <div :style=\"{ color, border: '1px' }\" />\n</template>\n\n<script setup lang=\"ts\">\nconst color = computed(() ="
  },
  {
    "path": "test/fixtures/Empty.vue",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "test/fixtures/Enum.vue",
    "chars": 118,
    "preview": "<template>\n  <div>{{ MyEnum }}</div>\n</template>\n\n<script setup lang=\"ts\">\nenum MyEnum {\n  test = 'true',\n}\n</script>\n"
  },
  {
    "path": "test/fixtures/HtmlTag.vue",
    "chars": 316,
    "preview": "<script setup lang=\"ts\">\nimport Enum from './Enum.vue'\nimport { ref } from '@vue/composition-api';\n\nlet p = \"hello word\""
  },
  {
    "path": "test/fixtures/HtmlTag2.vue",
    "chars": 479,
    "preview": "<script setup lang=\"ts\">\nimport Button from './DynamicStyle.vue';\nimport button from './DynamicStyle.vue';\nimport { defi"
  },
  {
    "path": "test/fixtures/JSLongComment.vue",
    "chars": 108,
    "preview": "<script setup lang=\"ts\">\nconst a = 1\n////////////////\n</script>\n<template>\n  <div>{{ a }}</div>\n</template>\n"
  },
  {
    "path": "test/fixtures/Macros.vue",
    "chars": 198,
    "preview": "<template>\n  <div @click=\"emit(props.msg)\">{{ msg }}</div>\n</template>\n\n<script setup lang=\"js\">\nconst props = definePro"
  },
  {
    "path": "test/fixtures/MacrosDefineExpose.vue",
    "chars": 275,
    "preview": "<template>\n  <div>{{ a }}</div>\n  <div>{{ text?.length ?? textLengthDefault }}</div>\n</template>\n\n<script setup lang=\"ts"
  },
  {
    "path": "test/fixtures/MacrosPure.vue",
    "chars": 118,
    "preview": "<template>\n  <div>{{ msg }}</div>\n</template>\n\n<script setup>\ndefineEmits()\ndefineProps({\n  msg: String,\n})\n</script>\n"
  },
  {
    "path": "test/fixtures/MacrosType.vue",
    "chars": 298,
    "preview": "<template>\n  <div @click=\"emit('update', props.msg)\">\n    {{ msg }}\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nconst"
  },
  {
    "path": "test/fixtures/MacrosType2.vue",
    "chars": 403,
    "preview": "<template>\n  <div @click=\"emit(props.msg)\">\n    {{ msg }}\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nexport interfac"
  },
  {
    "path": "test/fixtures/MacrosType3.vue",
    "chars": 327,
    "preview": "<template>\n  <div @click=\"emit('update', msg);emit('update', msg + value);\">\n    {{ msg }}\n  </div>\n</template>\n\n<script"
  },
  {
    "path": "test/fixtures/MacrosType4.vue",
    "chars": 127,
    "preview": "<script setup lang=\"ts\">\ntype Test = number[]\nwithDefaults(\n  defineProps<{ test: Test }>(),\n  { test: () => [] },\n)\n</s"
  },
  {
    "path": "test/fixtures/MacrosType5.vue",
    "chars": 81,
    "preview": "<script setup lang=\"ts\">\ndefineSlots<{\n  default: { msg: string }\n}>()\n</script>\n"
  },
  {
    "path": "test/fixtures/MacrosType6.vue",
    "chars": 248,
    "preview": "<script setup lang=\"ts\">\nconst slots = defineSlots<{\n  default: { msg: string }\n}>()\n</script>\n<template>\n  <template v-"
  },
  {
    "path": "test/fixtures/MacrosTypeAny.vue",
    "chars": 136,
    "preview": "<template>\n  <div>\n    {{ value }}\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nconst props = defineProps<{ value: any"
  },
  {
    "path": "test/fixtures/Object1.vue",
    "chars": 146,
    "preview": "<template>\n  <div>\n    {{ data }} {{ title }}\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nconst data = {\n  title: 'Te"
  },
  {
    "path": "test/fixtures/ObjectDestructure.vue",
    "chars": 175,
    "preview": "<template>\n  <div></div>\n</template>\n\n<script setup>\nimport { toRefs, reactive } from 'vue'\nconst state = reactive({ dat"
  },
  {
    "path": "test/fixtures/Pug1.vue",
    "chars": 189,
    "preview": "<template lang=\"pug\">\n.root\n  span {{ data }} {{ title }}\n  .p-1(@click=\"foo\")\n</template>\n\n<script setup lang=\"ts\">\ncon"
  },
  {
    "path": "test/fixtures/RefSugar.ts",
    "chars": 340,
    "preview": "/* eslint-disable unused-imports/no-unused-vars */\n/* eslint-disable prefer-const */\nimport { ref } from '@vue/compositi"
  },
  {
    "path": "test/fixtures/RefSugar.vue",
    "chars": 438,
    "preview": "<template>\n  <div>\n    {{ msg }}\n    {{ msg2 }}\n    {{ a }}\n  </div>\n</template>\n\n<script lang=\"ts\">\n/* eslint-disable p"
  },
  {
    "path": "test/fixtures/RefSugarScriptSetup.vue",
    "chars": 155,
    "preview": "<template>\n  <div>\n    {{ msg }}\n  </div>\n</template>\n\n<script setup lang=\"ts\">\n/* eslint-disable prefer-const */\n\nlet m"
  },
  {
    "path": "test/fixtures/ScriptLessThanOrEqualTo.vue",
    "chars": 110,
    "preview": "<script setup lang=\"ts\">\nconst val: boolean = 1 <= 2\n</script>\n\n<template>\n  <div>{{ val }}</div>\n</template>\n"
  },
  {
    "path": "test/fixtures/ScriptOnly.vue",
    "chars": 211,
    "preview": "<script lang=\"ts\">\n// <script setup> in comment should not be matched\nimport { defineComponent } from '@vue/composition-"
  },
  {
    "path": "test/fixtures/TemplateOnly.vue",
    "chars": 316,
    "preview": "<template>\n  <div>\n    <div v-for=\"(item, index) in items\" :key=\"item\">\n      {{ index }}: {{ item }}\n    </div>\n  </div"
  },
  {
    "path": "test/fixtures/TemplateOptionalChaining.vue",
    "chars": 487,
    "preview": "<template>\n  <div @click=\"callback?.()\">\n    {{ text?.length ?? textLengthDefault?.[index] }}\n    {{ classes?.[0] }}\n   "
  },
  {
    "path": "test/fixtures/VFor.vue",
    "chars": 465,
    "preview": "<template>\n  <div>\n    <div v-for=\"(item, index) in items\" :key=\"item\">\n      {{ item }}\n    </div>\n    <div v-for=\"{ ca"
  },
  {
    "path": "test/fixtures/VariableBinding.vue",
    "chars": 421,
    "preview": "<script setup lang=\"ts\">\n/* eslint-disable no-console */\nimport { reactive } from '@vue/composition-api'\nconst state = r"
  },
  {
    "path": "test/identifiers.test.ts",
    "chars": 2763,
    "preview": "/* eslint-disable no-template-curly-in-string */\nimport { parse } from '@babel/parser'\nimport { describe, expect, it } f"
  },
  {
    "path": "test/nativeTag.test.ts",
    "chars": 3081,
    "preview": "import { describe, expect, it } from 'vitest'\nimport { transform } from '../src'\n\ndescribe('filter native tags as vue co"
  },
  {
    "path": "test/transform.test.ts",
    "chars": 914,
    "preview": "import { resolve } from 'node:path'\nimport { promises as fs } from 'node:fs'\nimport fg from 'fast-glob'\nimport { describ"
  },
  {
    "path": "test/transform_filter.test.ts",
    "chars": 1887,
    "preview": "import { } from 'node:test'\nimport { describe, expect, it } from 'vitest'\nimport { scriptSetupRE } from '../src/core'\n\nd"
  },
  {
    "path": "tsconfig.json",
    "chars": 344,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es2017\",\n    \"module\": \"esnext\",\n    \"lib\": [\"esnext\", \"dom\"],\n    \"moduleResolu"
  },
  {
    "path": "types.d.ts",
    "chars": 39,
    "preview": "export { default } from './dist/types'\n"
  },
  {
    "path": "vite.d.ts",
    "chars": 38,
    "preview": "export { default } from './dist/vite'\n"
  },
  {
    "path": "webpack.d.ts",
    "chars": 41,
    "preview": "export { default } from './dist/webpack'\n"
  }
]

About this extraction

This page contains the full source code of the antfu/unplugin-vue2-script-setup GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 103 files (109.5 KB), approximately 32.9k tokens, and a symbol index with 50 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!