@katabatic/compiler 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/analyse/visitors/CustomElement.js +2 -0
- package/src/analyse/visitors/Element.js +4 -6
- package/src/builders.js +83 -10
- package/src/checkers.js +26 -6
- package/src/css-matcher.js +8 -9
- package/src/css.js +0 -54
- package/src/exp-matcher.js +12 -5
- package/src/transform/context.js +3 -5
- package/src/transform/visitors/Attribute.js +62 -36
- package/src/transform/visitors/CustomElement.js +10 -9
- package/src/transform/visitors/EachBlock.js +15 -5
- package/src/transform/visitors/Element.js +12 -31
- package/src/transform/visitors/IfBlock.js +15 -5
- package/src/transform/visitors/Template.js +7 -5
package/package.json
CHANGED
|
@@ -4,7 +4,9 @@ export function CustomElement(node, ctx) {
|
|
|
4
4
|
ctx.next()
|
|
5
5
|
|
|
6
6
|
const hasClass = node.attributes.some(is.classAttribute)
|
|
7
|
+
const hasExpressionAttribute = node.attributes.some(is.expressionAttribute)
|
|
7
8
|
|
|
8
9
|
node.metadata ??= {}
|
|
9
10
|
node.metadata.hasClass = hasClass
|
|
11
|
+
node.metadata.hasExpressionAttribute = hasExpressionAttribute
|
|
10
12
|
}
|
|
@@ -3,14 +3,12 @@ import * as is from '../../checkers.js'
|
|
|
3
3
|
export function Element(node, ctx) {
|
|
4
4
|
ctx.next()
|
|
5
5
|
|
|
6
|
+
const isVoid = is.voidElement(node)
|
|
6
7
|
const hasClass = node.attributes.some(is.classAttribute)
|
|
7
|
-
|
|
8
|
-
const bindAttribute = node.attributes.find(is.bindAttribute)
|
|
9
|
-
const hasBinding = !!bindAttribute
|
|
10
|
-
const bindExpression = bindAttribute?.value[0].expression
|
|
8
|
+
const hasExpressionAttribute = node.attributes.some(is.expressionAttribute)
|
|
11
9
|
|
|
12
10
|
node.metadata ??= {}
|
|
11
|
+
node.metadata.isVoid = isVoid
|
|
13
12
|
node.metadata.hasClass = hasClass
|
|
14
|
-
node.metadata.
|
|
15
|
-
node.metadata.bindExpression = bindExpression
|
|
13
|
+
node.metadata.hasExpressionAttribute = hasExpressionAttribute
|
|
16
14
|
}
|
package/src/builders.js
CHANGED
|
@@ -227,6 +227,10 @@ export function array(elements) {
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
export function call(callee, args = [], { optional = false } = {}) {
|
|
230
|
+
if (typeof callee === 'string') {
|
|
231
|
+
callee = { type: 'Identifier', name: callee }
|
|
232
|
+
}
|
|
233
|
+
|
|
230
234
|
return { type: 'CallExpression', callee, arguments: args, optional }
|
|
231
235
|
}
|
|
232
236
|
|
|
@@ -577,14 +581,7 @@ export function $set(object, nodeId, attribute, value) {
|
|
|
577
581
|
computed: false,
|
|
578
582
|
optional: false
|
|
579
583
|
},
|
|
580
|
-
arguments: [
|
|
581
|
-
nodeId,
|
|
582
|
-
{
|
|
583
|
-
type: 'Literal',
|
|
584
|
-
value: attribute
|
|
585
|
-
},
|
|
586
|
-
value
|
|
587
|
-
],
|
|
584
|
+
arguments: [nodeId, attribute, value],
|
|
588
585
|
optional: false
|
|
589
586
|
}
|
|
590
587
|
}
|
|
@@ -1064,6 +1061,82 @@ export function $effect(body) {
|
|
|
1064
1061
|
}
|
|
1065
1062
|
}
|
|
1066
1063
|
|
|
1064
|
+
export function $bind(elementId, body) {
|
|
1065
|
+
return {
|
|
1066
|
+
type: 'ExpressionStatement',
|
|
1067
|
+
expression: {
|
|
1068
|
+
type: 'CallExpression',
|
|
1069
|
+
callee: {
|
|
1070
|
+
type: 'MemberExpression',
|
|
1071
|
+
object: {
|
|
1072
|
+
type: 'MemberExpression',
|
|
1073
|
+
object: {
|
|
1074
|
+
type: 'ThisExpression'
|
|
1075
|
+
},
|
|
1076
|
+
property: {
|
|
1077
|
+
type: 'Identifier',
|
|
1078
|
+
name: '$'
|
|
1079
|
+
},
|
|
1080
|
+
computed: false,
|
|
1081
|
+
optional: false
|
|
1082
|
+
},
|
|
1083
|
+
property: {
|
|
1084
|
+
type: 'Identifier',
|
|
1085
|
+
name: 'bind'
|
|
1086
|
+
},
|
|
1087
|
+
computed: false,
|
|
1088
|
+
optional: false
|
|
1089
|
+
},
|
|
1090
|
+
arguments: [
|
|
1091
|
+
elementId,
|
|
1092
|
+
{
|
|
1093
|
+
type: 'ArrowFunctionExpression',
|
|
1094
|
+
id: null,
|
|
1095
|
+
expression: false,
|
|
1096
|
+
generator: false,
|
|
1097
|
+
async: false,
|
|
1098
|
+
params: [{ type: 'Identifier', name: 'opts' }],
|
|
1099
|
+
body
|
|
1100
|
+
},
|
|
1101
|
+
{
|
|
1102
|
+
type: 'Identifier',
|
|
1103
|
+
name: '$'
|
|
1104
|
+
}
|
|
1105
|
+
],
|
|
1106
|
+
optional: false
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
export function $getBinding(elementId) {
|
|
1112
|
+
return {
|
|
1113
|
+
type: 'CallExpression',
|
|
1114
|
+
callee: {
|
|
1115
|
+
type: 'MemberExpression',
|
|
1116
|
+
object: {
|
|
1117
|
+
type: 'MemberExpression',
|
|
1118
|
+
object: {
|
|
1119
|
+
type: 'ThisExpression'
|
|
1120
|
+
},
|
|
1121
|
+
property: {
|
|
1122
|
+
type: 'Identifier',
|
|
1123
|
+
name: '$'
|
|
1124
|
+
},
|
|
1125
|
+
computed: false,
|
|
1126
|
+
optional: false
|
|
1127
|
+
},
|
|
1128
|
+
property: {
|
|
1129
|
+
type: 'Identifier',
|
|
1130
|
+
name: 'getBinding'
|
|
1131
|
+
},
|
|
1132
|
+
computed: false,
|
|
1133
|
+
optional: false
|
|
1134
|
+
},
|
|
1135
|
+
arguments: [elementId],
|
|
1136
|
+
optional: false
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1067
1140
|
export function $animate(value, body) {
|
|
1068
1141
|
return {
|
|
1069
1142
|
type: 'ExpressionStatement',
|
|
@@ -1099,7 +1172,7 @@ export function $animate(value, body) {
|
|
|
1099
1172
|
}
|
|
1100
1173
|
}
|
|
1101
1174
|
|
|
1102
|
-
export function addEventListener(object, value, body) {
|
|
1175
|
+
export function addEventListener(object, value, body, { optional = false } = {}) {
|
|
1103
1176
|
return {
|
|
1104
1177
|
type: 'ExpressionStatement',
|
|
1105
1178
|
expression: {
|
|
@@ -1134,7 +1207,7 @@ export function addEventListener(object, value, body) {
|
|
|
1134
1207
|
}
|
|
1135
1208
|
}
|
|
1136
1209
|
],
|
|
1137
|
-
optional
|
|
1210
|
+
optional
|
|
1138
1211
|
}
|
|
1139
1212
|
}
|
|
1140
1213
|
}
|
package/src/checkers.js
CHANGED
|
@@ -121,6 +121,10 @@ export function classAttribute(node, withExpressionTag) {
|
|
|
121
121
|
return result
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
export function expressionAttribute(node) {
|
|
125
|
+
return node.type === 'Attribute' && node.value[0]?.type === 'ExpressionTag'
|
|
126
|
+
}
|
|
127
|
+
|
|
124
128
|
export function idAttribute(node, withExpressionTag) {
|
|
125
129
|
let result = node.type === 'Attribute' && node.name === 'id'
|
|
126
130
|
if (withExpressionTag === true) {
|
|
@@ -129,12 +133,6 @@ export function idAttribute(node, withExpressionTag) {
|
|
|
129
133
|
return result
|
|
130
134
|
}
|
|
131
135
|
|
|
132
|
-
export function bindAttribute(node) {
|
|
133
|
-
return (
|
|
134
|
-
node.type === 'Attribute' && node.name === 'bind' && node.value[0]?.type === 'ExpressionTag'
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
136
|
export function staticAttribute(node) {
|
|
139
137
|
return node.type === 'Attribute' && node.name === 'static'
|
|
140
138
|
}
|
|
@@ -146,3 +144,25 @@ export function shadowRootModeAttribute(node) {
|
|
|
146
144
|
export function elseIfBlock(node) {
|
|
147
145
|
return node.type === 'IfBlock' && node.elseif
|
|
148
146
|
}
|
|
147
|
+
|
|
148
|
+
export function voidElement(node) {
|
|
149
|
+
return (
|
|
150
|
+
node.type === 'Element' &&
|
|
151
|
+
[
|
|
152
|
+
'area',
|
|
153
|
+
'base',
|
|
154
|
+
'br',
|
|
155
|
+
'col',
|
|
156
|
+
'embed',
|
|
157
|
+
'hr',
|
|
158
|
+
'img',
|
|
159
|
+
'input',
|
|
160
|
+
'link',
|
|
161
|
+
'meta',
|
|
162
|
+
'param',
|
|
163
|
+
'source',
|
|
164
|
+
'track',
|
|
165
|
+
'wbr'
|
|
166
|
+
].includes(node.name)
|
|
167
|
+
)
|
|
168
|
+
}
|
package/src/css-matcher.js
CHANGED
|
@@ -54,21 +54,21 @@ function matchSelectors(selectors, template) {
|
|
|
54
54
|
classAttribute ??= node.attributes.find((a) => a.name === 'class')
|
|
55
55
|
scopedElement = node
|
|
56
56
|
scopedClassAttribute = classAttribute
|
|
57
|
-
break
|
|
58
57
|
}
|
|
59
|
-
|
|
58
|
+
break
|
|
60
59
|
case 'PseudoClassSelector':
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
if (selector.name !== 'host') {
|
|
61
|
+
classAttribute ??= node.attributes.find((a) => a.name === 'class')
|
|
62
|
+
scopedElement = node
|
|
63
|
+
scopedClassAttribute = classAttribute
|
|
64
|
+
}
|
|
64
65
|
break
|
|
65
66
|
case 'IdSelector':
|
|
66
67
|
const idAttribute = node.attributes.find((a) => a.name === 'id')
|
|
67
68
|
if (idAttribute?.value[0].data === selector.name) {
|
|
68
69
|
scopedIdAttribute = idAttribute
|
|
69
|
-
break
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
break
|
|
72
72
|
case 'ClassSelector':
|
|
73
73
|
classAttribute ??= node.attributes.find((a) => a.name === 'class')
|
|
74
74
|
const expression = classAttribute?.value[0].expression
|
|
@@ -76,9 +76,8 @@ function matchSelectors(selectors, template) {
|
|
|
76
76
|
|
|
77
77
|
if (expression || classes?.includes(selector.name)) {
|
|
78
78
|
scopedClassAttribute = classAttribute
|
|
79
|
-
break
|
|
80
79
|
}
|
|
81
|
-
|
|
80
|
+
break
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
|
package/src/css.js
CHANGED
|
@@ -1,57 +1,3 @@
|
|
|
1
|
-
export function match(element, stylesheet) {
|
|
2
|
-
for (const rule of stylesheet.children) {
|
|
3
|
-
if (matchSelectorList(element, rule.prelude)) return true
|
|
4
|
-
}
|
|
5
|
-
return false
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function matchSelectorList(element, selectorList) {
|
|
9
|
-
if (selectorList) {
|
|
10
|
-
for (const selector of selectorList.children) {
|
|
11
|
-
if (matchSelector(element, selector)) return true
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return false
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function matchSelector(element, selector) {
|
|
18
|
-
let selectors = []
|
|
19
|
-
for (const child of selector.children) {
|
|
20
|
-
switch (child.type) {
|
|
21
|
-
case 'TypeSelector':
|
|
22
|
-
case 'ClassSelector':
|
|
23
|
-
selectors.push(child)
|
|
24
|
-
break
|
|
25
|
-
case 'PseudoClassSelector':
|
|
26
|
-
if (matchSelectorList(element, child.children?.first)) return true
|
|
27
|
-
selectors.push(child)
|
|
28
|
-
break
|
|
29
|
-
case 'Combinator':
|
|
30
|
-
if (matchSelectors(element, selectors)) return true
|
|
31
|
-
selectors = []
|
|
32
|
-
break
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return matchSelectors(element, selectors)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function matchSelectors(element, selectors) {
|
|
39
|
-
if (selectors.length === 0) return false
|
|
40
|
-
|
|
41
|
-
for (const selector of selectors) {
|
|
42
|
-
switch (selector.type) {
|
|
43
|
-
case 'TypeSelector':
|
|
44
|
-
if (selector.name !== element.name) return false
|
|
45
|
-
break
|
|
46
|
-
case 'ClassSelector':
|
|
47
|
-
const classAtt = element.attributes.find((a) => a.name === 'class')?.value.data
|
|
48
|
-
const classes = classAtt?.split(/\s+/)
|
|
49
|
-
if (!classes?.includes(selector.name)) return false
|
|
50
|
-
break
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return true
|
|
54
|
-
}
|
|
55
1
|
|
|
56
2
|
/**
|
|
57
3
|
* Dead simple clx assuming class2 is always set
|
package/src/exp-matcher.js
CHANGED
|
@@ -12,21 +12,28 @@ export function matchExpression(expression, program, blocks) {
|
|
|
12
12
|
if (parentNode.callee === node) {
|
|
13
13
|
setMethodMetadata(node)
|
|
14
14
|
} else {
|
|
15
|
-
setMetadata(node)
|
|
15
|
+
setMetadata(node, blocks)
|
|
16
16
|
}
|
|
17
17
|
break
|
|
18
18
|
case 'MemberExpression':
|
|
19
19
|
if (parentNode.object === node) {
|
|
20
|
+
setMetadata(node, blocks)
|
|
21
|
+
}
|
|
22
|
+
break
|
|
23
|
+
case 'AssignmentExpression':
|
|
24
|
+
if (parentNode.left === node) {
|
|
20
25
|
setMetadata(node)
|
|
26
|
+
} else {
|
|
27
|
+
setMetadata(node, blocks)
|
|
21
28
|
}
|
|
22
29
|
break
|
|
23
30
|
case 'Property':
|
|
24
31
|
if (parentNode.value === node) {
|
|
25
|
-
setMetadata(node)
|
|
32
|
+
setMetadata(node, blocks)
|
|
26
33
|
}
|
|
27
34
|
break
|
|
28
35
|
default:
|
|
29
|
-
setMetadata(node)
|
|
36
|
+
setMetadata(node, blocks)
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
39
|
})
|
|
@@ -49,10 +56,10 @@ export function matchExpression(expression, program, blocks) {
|
|
|
49
56
|
node.metadata.isData = true
|
|
50
57
|
}
|
|
51
58
|
|
|
52
|
-
function setMetadata(node) {
|
|
59
|
+
function setMetadata(node, blocks) {
|
|
53
60
|
node.metadata ??= {}
|
|
54
61
|
|
|
55
|
-
if (blocks
|
|
62
|
+
if (blocks?.some((b) => b.context?.name === node.name)) {
|
|
56
63
|
node.metadata.isBlockVar = true
|
|
57
64
|
return
|
|
58
65
|
}
|
package/src/transform/context.js
CHANGED
|
@@ -12,10 +12,6 @@ export function nextBlockId(ctx) {
|
|
|
12
12
|
return b.id(`block_${ctx.state.blocks.length + 1}`)
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function nextBindingId(ctx) {
|
|
16
|
-
return b.id(`binding_${ctx.state.init.binding.length + 1}`)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
15
|
export function pathStmt(ctx, nodes) {
|
|
20
16
|
const subPath = []
|
|
21
17
|
|
|
@@ -58,7 +54,9 @@ function position(fragment, node) {
|
|
|
58
54
|
(nodes[i - 1]?.type === 'ExpressionTag' || nodes[i - 1]?.type === 'Text')
|
|
59
55
|
) {
|
|
60
56
|
// Text and ExpressionTag siblings are collapsed in one node in the html template
|
|
61
|
-
} else {
|
|
57
|
+
} else if (nodes[i].type === 'Comment') {
|
|
58
|
+
// Comments are skiped in the html template
|
|
59
|
+
} else {
|
|
62
60
|
position++
|
|
63
61
|
}
|
|
64
62
|
|
|
@@ -24,47 +24,73 @@ export function Attribute(node, ctx) {
|
|
|
24
24
|
ctx.visit(val, { ...ctx.state, template, pretty: false })
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
if (node.name === ':in' || node.name === ':out' || node.name === ':animate') {
|
|
28
|
+
const elementId = ctx.state.getElementId()
|
|
29
|
+
const expression = template.expressions[0]
|
|
30
|
+
const direction = node.name === ':animate' ? 'both' : node.name.slice(1)
|
|
31
|
+
const stmt = b.$animate(direction, {
|
|
32
|
+
...expression,
|
|
33
|
+
arguments: [elementId, expression.arguments[0] ?? b.object(), b.id('o')]
|
|
34
|
+
})
|
|
35
|
+
ctx.state.animates.push(stmt)
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (node.name === ':use') {
|
|
40
|
+
const elementId = ctx.state.getElementId()
|
|
41
|
+
const expression = template.expressions[0]
|
|
42
|
+
const bindExpression = {
|
|
43
|
+
...expression,
|
|
44
|
+
arguments: [elementId, b.call('opts', expression.arguments[0])]
|
|
45
|
+
}
|
|
46
|
+
const stmt = b.$bind(elementId, bindExpression)
|
|
47
|
+
ctx.state.binds.push(stmt)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (node.name.startsWith(':on')) {
|
|
52
|
+
const elementId = ctx.state.getElementId()
|
|
53
|
+
const expression = template.expressions[0]
|
|
54
|
+
const event = node.name.slice(3)
|
|
55
|
+
const stmt = b.addEventListener(b.$getBinding(elementId), event, [expression], {
|
|
56
|
+
optional: true
|
|
57
|
+
})
|
|
58
|
+
ctx.state.eventListeners.push(stmt)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (node.name.startsWith(':')) {
|
|
63
|
+
const elementId = ctx.state.getElementId()
|
|
64
|
+
const property = node.name.slice(1)
|
|
65
|
+
const stmt = b.$effect([
|
|
66
|
+
b.assignment(b.member(b.$getBinding(elementId), property), b.template(template))
|
|
67
|
+
])
|
|
68
|
+
ctx.state.effects.push(stmt)
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (node.name.startsWith('on')) {
|
|
73
|
+
const elementId = ctx.state.getElementId()
|
|
74
|
+
const expression = template.expressions[0]
|
|
75
|
+
const event = node.name.slice(2)
|
|
76
|
+
const stmt = b.addEventListener(elementId, event, [expression])
|
|
77
|
+
ctx.state.eventListeners.push(stmt)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
27
81
|
if (hasExpression(template)) {
|
|
28
|
-
// expression attribute
|
|
29
82
|
const elementId = ctx.state.getElementId()
|
|
30
83
|
const moduleId = ctx.state.getModuleId?.()
|
|
31
|
-
const bindingId = ctx.state.getBindingId?.()
|
|
32
84
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
arguments: [elementId, animateExpression.arguments[0] ?? b.object(), b.id('o')]
|
|
41
|
-
})
|
|
42
|
-
ctx.state.animates.push(stmt)
|
|
43
|
-
} else if (node.name.startsWith('on')) {
|
|
44
|
-
const stmt = b.assignment(
|
|
45
|
-
b.member(elementId, node.name),
|
|
46
|
-
b.eventListener(template.expressions[0])
|
|
47
|
-
)
|
|
48
|
-
ctx.state.handlers.push(stmt)
|
|
49
|
-
} else if (moduleId) {
|
|
50
|
-
const stmt = b.$effect([b.$set(moduleId, elementId, node.name, b.template(template))])
|
|
51
|
-
ctx.state.effects.push(stmt)
|
|
52
|
-
} else if (bindingId) {
|
|
53
|
-
const stmt1 = b.$effect([
|
|
54
|
-
b.assignment(b.member(bindingId, node.name), b.template(template))
|
|
55
|
-
])
|
|
56
|
-
const stmt2 = b.$effect([
|
|
57
|
-
b.assignment(template.expressions[0], b.member(bindingId, node.name))
|
|
58
|
-
])
|
|
85
|
+
const setStmt = moduleId
|
|
86
|
+
? b.$set(moduleId, elementId, b.literal(node.name), b.template(template))
|
|
87
|
+
: b.setAttribute(elementId, b.literal(node.name), b.template(template))
|
|
88
|
+
const stmt = b.$effect([setStmt])
|
|
89
|
+
ctx.state.effects.push(stmt)
|
|
90
|
+
return
|
|
91
|
+
}
|
|
59
92
|
|
|
60
|
-
|
|
61
|
-
} else {
|
|
62
|
-
const stmt = b.$effect([
|
|
63
|
-
b.setAttribute(elementId, b.literal(node.name), b.template(template))
|
|
64
|
-
])
|
|
65
|
-
ctx.state.effects.push(stmt)
|
|
66
|
-
}
|
|
67
|
-
} else if (isEmpty(template)) {
|
|
93
|
+
if (isEmpty(template)) {
|
|
68
94
|
appendText(ctx.state.template, ` ${node.name}`)
|
|
69
95
|
} else {
|
|
70
96
|
appendText(ctx.state.template, ` ${node.name}="${template.text[0]}"`)
|
|
@@ -9,13 +9,10 @@ export function CustomElement(node, ctx) {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
let elementId
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
ctx.state.init.elem.push(stmt)
|
|
17
|
-
}
|
|
18
|
-
return elementId
|
|
12
|
+
if (node.metadata?.hasExpressionAttribute) {
|
|
13
|
+
elementId = nextElementId(ctx)
|
|
14
|
+
const stmt = b.declaration(elementId, pathStmt(ctx, node))
|
|
15
|
+
ctx.state.init.elem.push(stmt)
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
if (node.metadata?.isModule) {
|
|
@@ -24,7 +21,11 @@ export function CustomElement(node, ctx) {
|
|
|
24
21
|
appendText(ctx.state.template, '<')
|
|
25
22
|
appendExpression(ctx.state.template, b.$name(moduleId))
|
|
26
23
|
for (const attribute of attributes) {
|
|
27
|
-
ctx.visit(attribute, {
|
|
24
|
+
ctx.visit(attribute, {
|
|
25
|
+
...ctx.state,
|
|
26
|
+
getElementId: () => elementId,
|
|
27
|
+
getModuleId: () => moduleId
|
|
28
|
+
})
|
|
28
29
|
}
|
|
29
30
|
appendText(ctx.state.template, '>')
|
|
30
31
|
ctx.visit(node.fragment)
|
|
@@ -34,7 +35,7 @@ export function CustomElement(node, ctx) {
|
|
|
34
35
|
} else {
|
|
35
36
|
appendText(ctx.state.template, `<${node.name}`)
|
|
36
37
|
for (const attribute of attributes) {
|
|
37
|
-
ctx.visit(attribute, { ...ctx.state, getElementId })
|
|
38
|
+
ctx.visit(attribute, { ...ctx.state, getElementId: () => elementId })
|
|
38
39
|
}
|
|
39
40
|
appendText(ctx.state.template, '>')
|
|
40
41
|
ctx.visit(node.fragment)
|
|
@@ -4,13 +4,23 @@ import { nextElementId, pathStmt } from '../context.js'
|
|
|
4
4
|
|
|
5
5
|
export function EachBlock(node, ctx) {
|
|
6
6
|
const template = { text: [''], expressions: [] }
|
|
7
|
-
const init = { elem: [], text: []
|
|
7
|
+
const init = { elem: [], text: [] }
|
|
8
|
+
const binds = []
|
|
8
9
|
const effects = []
|
|
9
10
|
const animates = []
|
|
10
|
-
const
|
|
11
|
+
const eventListeners = []
|
|
11
12
|
const blocks = []
|
|
12
13
|
|
|
13
|
-
ctx.visit(node.body, {
|
|
14
|
+
ctx.visit(node.body, {
|
|
15
|
+
...ctx.state,
|
|
16
|
+
template,
|
|
17
|
+
init,
|
|
18
|
+
binds,
|
|
19
|
+
effects,
|
|
20
|
+
animates,
|
|
21
|
+
eventListeners,
|
|
22
|
+
blocks
|
|
23
|
+
})
|
|
14
24
|
|
|
15
25
|
const stmts1 = [
|
|
16
26
|
b.declaration('template', b.createElement('template')),
|
|
@@ -19,10 +29,10 @@ export function EachBlock(node, ctx) {
|
|
|
19
29
|
const stmts2 = [
|
|
20
30
|
...init.elem,
|
|
21
31
|
...init.text,
|
|
22
|
-
...
|
|
32
|
+
...binds,
|
|
23
33
|
...effects,
|
|
24
34
|
...animates,
|
|
25
|
-
...
|
|
35
|
+
...eventListeners,
|
|
26
36
|
...blocks
|
|
27
37
|
]
|
|
28
38
|
const stmt3 = b.insertBefore('anchor', b.member('template', 'content'))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as b from '../../builders.js'
|
|
2
2
|
import { appendText } from '../../utils/template.js'
|
|
3
|
-
import {
|
|
3
|
+
import { nextElementId, pathStmt } from '../context.js'
|
|
4
4
|
|
|
5
5
|
export function Element(node, ctx) {
|
|
6
6
|
let attributes = node.attributes
|
|
@@ -8,41 +8,22 @@ export function Element(node, ctx) {
|
|
|
8
8
|
attributes = [...attributes, b.attribute('class', '', { isScoped: true })]
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const changed = []
|
|
12
|
-
|
|
13
11
|
let elementId
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
ctx.state.init.elem.push(stmt)
|
|
19
|
-
}
|
|
20
|
-
return elementId
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let bindingId
|
|
24
|
-
function getBindingId() {
|
|
25
|
-
if (!bindingId && node.metadata?.hasBinding) {
|
|
26
|
-
bindingId = nextBindingId(ctx)
|
|
27
|
-
const stmt = b.declaration(bindingId, {
|
|
28
|
-
...node.metadata?.bindExpression,
|
|
29
|
-
arguments: [getElementId(), ...node.metadata?.bindExpression.arguments]
|
|
30
|
-
})
|
|
31
|
-
ctx.state.init.binding.push(stmt)
|
|
32
|
-
}
|
|
33
|
-
return bindingId
|
|
12
|
+
if (node.metadata?.hasExpressionAttribute) {
|
|
13
|
+
elementId = nextElementId(ctx)
|
|
14
|
+
const stmt = b.declaration(elementId, pathStmt(ctx, node))
|
|
15
|
+
ctx.state.init.elem.push(stmt)
|
|
34
16
|
}
|
|
35
17
|
|
|
36
18
|
appendText(ctx.state.template, `<${node.name}`)
|
|
37
19
|
for (const attribute of attributes) {
|
|
38
|
-
ctx.visit(attribute, { ...ctx.state, getElementId
|
|
20
|
+
ctx.visit(attribute, { ...ctx.state, getElementId: () => elementId })
|
|
39
21
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
ctx.state.handlers.push(stmt)
|
|
22
|
+
if (node.metadata?.isVoid) {
|
|
23
|
+
appendText(ctx.state.template, '/>')
|
|
24
|
+
} else {
|
|
25
|
+
appendText(ctx.state.template, '>')
|
|
26
|
+
ctx.visit(node.fragment, { ...ctx.state, getElementId: () => elementId })
|
|
27
|
+
appendText(ctx.state.template, `</${node.name}>`)
|
|
47
28
|
}
|
|
48
29
|
}
|
|
@@ -6,13 +6,23 @@ export function IfBlock(node, ctx) {
|
|
|
6
6
|
function branchStmt(node, hasElseif = false) {
|
|
7
7
|
if (node) {
|
|
8
8
|
const template = { text: [''], expressions: [] }
|
|
9
|
-
const init = { elem: [], text: []
|
|
9
|
+
const init = { elem: [], text: [] }
|
|
10
|
+
const binds = []
|
|
10
11
|
const effects = []
|
|
11
12
|
const animates = []
|
|
12
|
-
const
|
|
13
|
+
const eventListeners = []
|
|
13
14
|
const blocks = []
|
|
14
15
|
|
|
15
|
-
ctx.visit(node, {
|
|
16
|
+
ctx.visit(node, {
|
|
17
|
+
...ctx.state,
|
|
18
|
+
template,
|
|
19
|
+
init,
|
|
20
|
+
binds,
|
|
21
|
+
effects,
|
|
22
|
+
animates,
|
|
23
|
+
eventListeners,
|
|
24
|
+
blocks
|
|
25
|
+
})
|
|
16
26
|
|
|
17
27
|
if (!hasElseif) {
|
|
18
28
|
const stmts1 = [
|
|
@@ -22,10 +32,10 @@ export function IfBlock(node, ctx) {
|
|
|
22
32
|
const stmts2 = [
|
|
23
33
|
...init.elem,
|
|
24
34
|
...init.text,
|
|
25
|
-
...
|
|
35
|
+
...binds,
|
|
26
36
|
...effects,
|
|
27
37
|
...animates,
|
|
28
|
-
...
|
|
38
|
+
...eventListeners,
|
|
29
39
|
...blocks
|
|
30
40
|
]
|
|
31
41
|
const stmt3 = b.insertBefore('anchor', b.member('template', 'content'))
|
|
@@ -3,10 +3,11 @@ import * as b from '../../builders.js'
|
|
|
3
3
|
export function Template(node, ctx) {
|
|
4
4
|
const style = { text: [''], expressions: [] }
|
|
5
5
|
const template = { text: [''], expressions: [] }
|
|
6
|
-
const init = { elem: [], text: []
|
|
6
|
+
const init = { elem: [], text: [] }
|
|
7
|
+
const binds = []
|
|
7
8
|
const effects = []
|
|
8
9
|
const animates = []
|
|
9
|
-
const
|
|
10
|
+
const eventListeners = []
|
|
10
11
|
const blocks = []
|
|
11
12
|
|
|
12
13
|
ctx.visit(node.fragment, {
|
|
@@ -14,9 +15,10 @@ export function Template(node, ctx) {
|
|
|
14
15
|
style,
|
|
15
16
|
template,
|
|
16
17
|
init,
|
|
18
|
+
binds,
|
|
17
19
|
effects,
|
|
18
20
|
animates,
|
|
19
|
-
|
|
21
|
+
eventListeners,
|
|
20
22
|
blocks
|
|
21
23
|
})
|
|
22
24
|
|
|
@@ -29,10 +31,10 @@ export function Template(node, ctx) {
|
|
|
29
31
|
const stmts2 = [
|
|
30
32
|
...init.elem,
|
|
31
33
|
...init.text,
|
|
32
|
-
...
|
|
34
|
+
...binds,
|
|
33
35
|
...effects,
|
|
34
36
|
...animates,
|
|
35
|
-
...
|
|
37
|
+
...eventListeners,
|
|
36
38
|
...blocks
|
|
37
39
|
]
|
|
38
40
|
const stmt3 = b.replaceChildren(rootId, b.member('template', 'content'))
|