Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.

Commit 3f1d393

Browse files
committed
feat: add defineSlots macro support
1 parent dd9cba0 commit 3f1d393

File tree

4 files changed

+71
-2
lines changed

4 files changed

+71
-2
lines changed

src/core/macros.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const DEFINE_PROPS = 'defineProps'
1818
const DEFINE_EMITS = 'defineEmits'
1919
const DEFINE_EXPOSE = 'defineExpose'
2020
const WITH_DEFAULTS = 'withDefaults'
21+
const DEFINE_SLOTS = 'defineSlots'
2122

2223
export interface PropTypeData {
2324
key: string
@@ -28,6 +29,7 @@ export interface PropTypeData {
2829
export function applyMacros(nodes: Statement[]) {
2930
let hasDefinePropsCall = false
3031
let hasDefineEmitCall = false
32+
let hasDefineSlotsCall = false
3133
let propsRuntimeDecl: Node | undefined
3234
let propsRuntimeDefaults: Node | undefined
3335
let propsTypeDecl: TSTypeLiteral | TSInterfaceBody | undefined
@@ -204,6 +206,23 @@ export function applyMacros(nodes: Statement[]) {
204206
return true
205207
}
206208

209+
function processDefineSlots(
210+
node: Node,
211+
): boolean {
212+
if (!isCallOf(node, DEFINE_SLOTS))
213+
return false
214+
215+
if (hasDefineSlotsCall)
216+
error(`duplicate ${DEFINE_SLOTS}() call`, node)
217+
218+
hasDefineSlotsCall = true
219+
220+
if (node.arguments.length > 0)
221+
error(`${DEFINE_SLOTS}() cannot accept arguments`, node)
222+
223+
return true
224+
}
225+
207226
function genRuntimeProps(props: Record<string, PropTypeData>) {
208227
const keys = Object.keys(props)
209228
if (!keys.length)
@@ -270,7 +289,9 @@ export function applyMacros(nodes: Statement[]) {
270289
const decl = node.declarations[i]
271290
if (decl.init) {
272291
if (processDefineEmits(decl.init))
273-
decl.init = t.memberExpression(t.identifier('__ctx'), t.identifier('emit')) as any
292+
decl.init = t.memberExpression(t.identifier('__ctx'), t.identifier('emit'))
293+
else if (processDefineSlots(decl.init))
294+
decl.init = t.memberExpression(t.identifier('__ctx'), t.identifier('slots'))
274295
else if (processDefineProps(decl.init) || processWithDefaults(decl.init))
275296
decl.init = t.identifier('__props') as any
276297
else
@@ -279,7 +300,7 @@ export function applyMacros(nodes: Statement[]) {
279300
}
280301
}
281302

282-
if (processWithDefaults(node) || processDefineEmits(node) || processDefineProps(node) || processDefineExpose(node))
303+
if (processWithDefaults(node) || processDefineEmits(node) || processDefineProps(node) || processDefineExpose(node) || processDefineSlots(node))
283304
return null
284305

285306
throwIfAwait(node)

test/__snapshots__/transform.test.ts.snap

+30
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,36 @@ export default __sfc_main;
677677
"
678678
`;
679679
680+
exports[`transform > fixtures > test/fixtures/MacrosType5.vue 1`] = `
681+
"<script lang=\\"ts\\">
682+
const __sfc_main = {};
683+
export default __sfc_main;
684+
</script>
685+
"
686+
`;
687+
688+
exports[`transform > fixtures > test/fixtures/MacrosType6.vue 1`] = `
689+
"<script lang=\\"ts\\">
690+
const __sfc_main = {};
691+
__sfc_main.setup = (__props, __ctx) => {
692+
const slots = __ctx.slots;
693+
return {
694+
slots
695+
};
696+
};
697+
export default __sfc_main;
698+
</script>
699+
<template>
700+
<template v-if=\\"slots.default\\">
701+
<slot name=\\"default\\" msg=\\"hello\\"></slot>
702+
</template>
703+
<div v-else>
704+
fallback
705+
</div>
706+
</template>
707+
"
708+
`;
709+
680710
exports[`transform > fixtures > test/fixtures/MacrosTypeAny.vue 1`] = `
681711
"<template>
682712
<div>

test/fixtures/MacrosType5.vue

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script setup lang="ts">
2+
defineSlots<{
3+
default: { msg: string }
4+
}>()
5+
</script>

test/fixtures/MacrosType6.vue

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script setup lang="ts">
2+
const slots = defineSlots<{
3+
default: { msg: string }
4+
}>()
5+
</script>
6+
<template>
7+
<template v-if="slots.default">
8+
<slot name="default" msg="hello"></slot>
9+
</template>
10+
<div v-else>
11+
fallback
12+
</div>
13+
</template>

0 commit comments

Comments
 (0)