-
-
Notifications
You must be signed in to change notification settings - Fork 106
/
Copy pathtransformElement.ts
92 lines (84 loc) · 2.26 KB
/
transformElement.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import {
type ElementNode,
type AttributeNode,
NodeTypes,
ElementTypes,
} from '@vue/compiler-dom'
import { isBuiltInDirective, isVoidTag } from '@vue/shared'
import { NodeTransform, TransformContext } from '../transform'
import { VaporDirectiveNode, IRNodeTypes } from '../ir'
export const transformElement: NodeTransform = (node, ctx) => {
return function postTransformElement() {
node = ctx.node
if (
!(
node.type === NodeTypes.ELEMENT &&
(node.tagType === ElementTypes.ELEMENT ||
node.tagType === ElementTypes.COMPONENT)
)
) {
return
}
const { tag, props } = node
const isComponent = node.tagType === ElementTypes.COMPONENT
if (isComponent) {
ctx.dynamic.ghost = true
ctx.registerOperation({
type: IRNodeTypes.CREATE_COMPONENT_NODE,
loc: node.loc,
id: ctx.reference(),
tag,
})
} else {
ctx.template += `<${tag}`
}
if (props.length) {
buildProps(
node,
ctx as TransformContext<ElementNode>,
undefined,
isComponent,
)
}
if (!isComponent) {
ctx.template += `>` + ctx.childrenTemplate.join('')
}
// TODO remove unnecessary close tag, e.g. if it's the last element of the template
if (!isVoidTag(tag)) {
ctx.template += `</${tag}>`
}
}
}
function buildProps(
node: ElementNode,
context: TransformContext<ElementNode>,
props: ElementNode['props'] = node.props,
isComponent: boolean,
) {
for (const prop of props) {
transformProp(prop as VaporDirectiveNode | AttributeNode, node, context)
}
}
function transformProp(
prop: VaporDirectiveNode | AttributeNode,
node: ElementNode,
context: TransformContext<ElementNode>,
): void {
const { name, loc } = prop
if (prop.type === NodeTypes.ATTRIBUTE) {
context.template += ` ${name}`
if (prop.value) context.template += `="${prop.value.content}"`
return
}
const directiveTransform = context.options.directiveTransforms[name]
if (directiveTransform) {
directiveTransform(prop, node, context)
} else if (!isBuiltInDirective(name)) {
context.registerOperation({
type: IRNodeTypes.WITH_DIRECTIVE,
element: context.reference(),
dir: prop,
loc,
})
}
}