|
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