Skip to content

Commit

Permalink
feat(volar): jsx-directive supports typescript for slotName (#468)
Browse files Browse the repository at this point in the history
* feat(volar): jsx-directive supports typescript for slotName

* chore: add changeset
  • Loading branch information
zhiyuanzmj committed Aug 19, 2023
1 parent 245a2ad commit 01132e0
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 51 deletions.
5 changes: 5 additions & 0 deletions .changeset/honest-waves-wink.md
@@ -0,0 +1,5 @@
---
'@vue-macros/volar': patch
---

jsx-directive supports typescript for slotName
119 changes: 68 additions & 51 deletions packages/volar/src/jsx-directive.ts
Expand Up @@ -187,23 +187,25 @@ function transformVSlot({
).escapedText === 'v-slot'
)

const slots =
const slotMap = new Map(
attribute && ts.isJsxAttribute(attribute)
? {
[`${
? [
[
ts.isJsxNamespacedName(attribute.name)
? attribute.name.name.escapedText
: 'default'
}`]: {
isTemplateTag: false,
initializer: attribute.initializer,
children: [...node.children],
},
}
: {}
? attribute.name.name
: undefined,
{
isTemplateTag: false,
initializer: attribute.initializer,
children: [...node.children],
},
],
]
: []
)
if (!attribute) {
for (const child of node.children) {
let name = 'default'
let name
let initializer
const isTemplateTag =
ts.isJsxElement(child) &&
Expand All @@ -215,8 +217,8 @@ function transformVSlot({
if (!ts.isJsxAttribute(attr)) continue
if (isTemplateTag) {
name = ts.isJsxNamespacedName(attr.name)
? `${attr.name.name.escapedText}`
: 'default'
? attr.name.name
: undefined
}

if (
Expand All @@ -229,56 +231,71 @@ function transformVSlot({
}
}

slots[name] ??= {
isTemplateTag,
initializer,
children: [child],
if (!slotMap.get(name)) {
slotMap.set(name, {
isTemplateTag,
initializer,
children: [child],
})
}
if (!slots[name].isTemplateTag) {
slots[name].initializer = initializer
slots[name].isTemplateTag = isTemplateTag
const slot = slotMap.get(name)!
if (slot && !slot?.isTemplateTag) {
slot.initializer = initializer
slot.isTemplateTag = isTemplateTag
if (isTemplateTag) {
slots[name].children = [child]
slot.children = [child]
} else {
slots[name].children.push(child)
slot.children.push(child)
}
}
}
}

const result = [
' v-slots={{',
...Object.entries(slots).flatMap(([name, { initializer, children }]) => [
`'${name}': (`,
initializer && ts.isJsxExpression(initializer) && initializer.expression
? [
`${sfc[source]!.content.slice(
...Array.from(slotMap.entries()).flatMap(
([name, { initializer, children }]) => [
name
? [
`'${name.escapedText}'`,
source,
name.pos - 1,
FileRangeCapabilities.full,
]
: 'default',
`: (`,
initializer &&
ts.isJsxExpression(initializer) &&
initializer.expression
? [
`${sfc[source]!.content.slice(
initializer.expression.pos,
initializer.expression.end
)}`,
source,
initializer.expression.pos,
initializer.expression.end
)}`,
FileRangeCapabilities.full,
]
: '',
') => <>',
...children.map((child) => {
const node =
ts.isJsxElement(child) &&
ts.isIdentifier(child.openingElement.tagName) &&
child.openingElement.tagName.escapedText === 'template'
? child.children
: child
replaceSourceRange(codes, source, child.pos, child.end)
return [
sfc[source]!.content.slice(node.pos, node.end),
source,
initializer.expression.pos,
node.pos,
FileRangeCapabilities.full,
]
: '',
') => <>',
...children.map((child) => {
const node =
ts.isJsxElement(child) &&
ts.isIdentifier(child.openingElement.tagName) &&
child.openingElement.tagName.escapedText === 'template'
? child.children
: child
replaceSourceRange(codes, source, child.pos, child.end)
return [
sfc[source]!.content.slice(node.pos, node.end),
source,
node.pos,
FileRangeCapabilities.full,
]
}),
'</>,',
]),
}),
'</>,',
]
),
`} as InstanceType<typeof ${node.openingElement.tagName.escapedText}>['$slots'] }`,
] as Segment<FileRangeCapabilities>[]

Expand Down

0 comments on commit 01132e0

Please sign in to comment.