|
1 |
| -import { camelize, capitalize } from '@vue/shared' |
| 1 | +import { capitalize } from '@vue/shared' |
2 | 2 | import type { Node, ObjectExpression, Statement } from '@babel/types'
|
3 | 3 | import generate from '@babel/generator'
|
4 | 4 | import { partition } from '@antfu/utils'
|
5 | 5 | import { ParsedSFC, ScriptSetupTransformOptions } from '../types'
|
6 | 6 | import { applyMacros } from './macros'
|
7 | 7 | import { getIdentifierDeclarations } from './identifiers'
|
8 | 8 | import { t } from './babel'
|
| 9 | +import { isNotNil, pascalize } from './utils' |
9 | 10 |
|
10 | 11 | function isAsyncImport(node: any) {
|
11 | 12 | if (node.type === 'VariableDeclaration') {
|
@@ -35,22 +36,29 @@ export function transformScriptSetup(sfc: ParsedSFC, options?: ScriptSetupTransf
|
35 | 36 | const declarations = new Set<string>()
|
36 | 37 | getIdentifierDeclarations(hoisted, declarations)
|
37 | 38 | getIdentifierDeclarations(setupBody, declarations)
|
| 39 | + const declarationArray = Array.from(declarations).filter(isNotNil) |
38 | 40 |
|
39 | 41 | // filter out identifiers that are used in `<template>`
|
40 |
| - const returns: ObjectExpression['properties'] = Array.from(declarations) |
41 |
| - .filter(Boolean) |
| 42 | + const returns: ObjectExpression['properties'] = declarationArray |
42 | 43 | .filter(i => template.identifiers.has(i))
|
43 | 44 | .map((i) => {
|
44 | 45 | const id = t.identifier(i)
|
45 | 46 | return t.objectProperty(id, id, false, true)
|
46 | 47 | })
|
47 | 48 |
|
48 |
| - const components = Array.from(declarations) |
49 |
| - .filter(Boolean) |
50 |
| - .filter(i => template.components.has(i) |
51 |
| - || template.components.has(camelize(i)) |
52 |
| - || template.components.has(capitalize(camelize(i))), |
53 |
| - ) |
| 49 | + const components = Array.from(template.components).map(component => |
| 50 | + declarationArray.find(declare => declare === component) |
| 51 | + ?? declarationArray.find(declare => pascalize(declare) === component), |
| 52 | + ).filter(isNotNil) |
| 53 | + |
| 54 | + const directiveDeclaration = Array.from(template.directives).map((directive) => { |
| 55 | + const identifier = declarationArray.find(declaration => declaration === `v${capitalize(directive)}`) |
| 56 | + if (identifier === undefined) |
| 57 | + return undefined |
| 58 | + |
| 59 | + return { identifier, directive } |
| 60 | + }, |
| 61 | + ).filter(isNotNil) |
54 | 62 |
|
55 | 63 | // append `<script setup>` imports to `<script>`
|
56 | 64 |
|
@@ -160,6 +168,35 @@ export function transformScriptSetup(sfc: ParsedSFC, options?: ScriptSetupTransf
|
160 | 168 | )
|
161 | 169 | }
|
162 | 170 |
|
| 171 | + // inject directives |
| 172 | + // `__sfc_main.directives = Object.assign({ ... }, __sfc_main.directives)` |
| 173 | + if (directiveDeclaration.length) { |
| 174 | + hasBody = true |
| 175 | + const directivesObject = t.objectExpression( |
| 176 | + directiveDeclaration.map(({ directive, identifier }) => (t.objectProperty( |
| 177 | + t.identifier(directive), |
| 178 | + t.identifier(identifier), |
| 179 | + false, |
| 180 | + false, |
| 181 | + ))), |
| 182 | + ) |
| 183 | + |
| 184 | + ast.body.push( |
| 185 | + t.expressionStatement( |
| 186 | + t.assignmentExpression('=', |
| 187 | + t.memberExpression(__sfc, t.identifier('directives')), |
| 188 | + t.callExpression( |
| 189 | + t.memberExpression(t.identifier('Object'), t.identifier('assign')), |
| 190 | + [ |
| 191 | + directivesObject, |
| 192 | + t.memberExpression(__sfc, t.identifier('directives')), |
| 193 | + ], |
| 194 | + ), |
| 195 | + ), |
| 196 | + ) as any, |
| 197 | + ) |
| 198 | + } |
| 199 | + |
163 | 200 | if (!hasBody && !options?.astTransforms) {
|
164 | 201 | return {
|
165 | 202 | ast: null,
|
|
0 commit comments