Skip to content

Commit bdcba5c

Browse files
authored
Support for <svelte:element> (#156)
1 parent 00d9f76 commit bdcba5c

24 files changed

+8090
-13
lines changed

src/parser/converts/element.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,11 @@ export function* convertChildren(
8282
continue
8383
}
8484
if (child.type === "Element") {
85-
yield convertHTMLElement(child, parent, ctx)
85+
if (child.name.includes(":")) {
86+
yield convertSpecialElement(child, parent, ctx)
87+
} else {
88+
yield convertHTMLElement(child, parent, ctx)
89+
}
8690
continue
8791
}
8892
if (child.type === "InlineComponent") {
@@ -277,6 +281,7 @@ function convertHTMLElement(
277281
function convertSpecialElement(
278282
node:
279283
| SvAST.InlineComponent
284+
| SvAST.Element
280285
| SvAST.Window
281286
| SvAST.Body
282287
| SvAST.Head
@@ -330,20 +335,18 @@ function convertSpecialElement(
330335
ctx.scriptLet.closeScope()
331336
}
332337

333-
if (
334-
node.type === "InlineComponent" &&
335-
node.expression &&
336-
node.name === "svelte:component"
337-
) {
338+
const thisExpression =
339+
(node.type === "InlineComponent" &&
340+
node.name === "svelte:component" &&
341+
node.expression) ||
342+
(node.type === "Element" && node.name === "svelte:element" && node.tag)
343+
if (thisExpression) {
338344
const eqIndex = ctx.code.lastIndexOf(
339345
"=",
340-
getWithLoc(node.expression).start,
346+
getWithLoc(thisExpression).start,
341347
)
342348
const startIndex = ctx.code.lastIndexOf("this", eqIndex)
343-
const closeIndex = ctx.code.indexOf(
344-
"}",
345-
getWithLoc(node.expression).end,
346-
)
349+
const closeIndex = ctx.code.indexOf("}", getWithLoc(thisExpression).end)
347350
const endIndex = indexOf(
348351
ctx.code,
349352
(c) => c === ">" || !c.trim(),
@@ -366,7 +369,7 @@ function convertSpecialElement(
366369
start: startIndex,
367370
end: eqIndex,
368371
})
369-
ctx.scriptLet.addExpression(node.expression, thisAttr, null, (es) => {
372+
ctx.scriptLet.addExpression(thisExpression, thisAttr, null, (es) => {
370373
thisAttr.expression = es
371374
})
372375
element.startTag.attributes.push(thisAttr)

src/parser/svelte-ast-types.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,22 @@ export interface KeyBlock extends BaseNode {
106106
children: TemplateNode[]
107107
}
108108

109-
export interface Element extends BaseNode {
109+
export interface BaseElement extends BaseNode {
110110
type: "Element"
111111
name: string
112112
children: TemplateNode[]
113113
attributes: AttributeOrDirective[]
114114
}
115+
116+
export interface BasicElement extends BaseElement {
117+
tag?: undefined
118+
}
119+
export interface SvelteComponent extends BaseElement {
120+
name: "svelte:element"
121+
tag: ESTree.Expression
122+
}
123+
export type Element = BasicElement | SvelteComponent
124+
115125
export interface BaseInlineComponent extends BaseNode {
116126
type: "InlineComponent"
117127
name: string
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<svelte:element this={expression}/>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"ruleId": "no-undef",
4+
"code": "expression",
5+
"line": 1,
6+
"column": 23
7+
}
8+
]
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
{
2+
"type": "Program",
3+
"body": [
4+
{
5+
"type": "SvelteElement",
6+
"kind": "special",
7+
"name": {
8+
"type": "SvelteName",
9+
"name": "svelte:element",
10+
"range": [
11+
1,
12+
15
13+
],
14+
"loc": {
15+
"start": {
16+
"line": 1,
17+
"column": 1
18+
},
19+
"end": {
20+
"line": 1,
21+
"column": 15
22+
}
23+
}
24+
},
25+
"startTag": {
26+
"type": "SvelteStartTag",
27+
"attributes": [
28+
{
29+
"type": "SvelteSpecialDirective",
30+
"kind": "this",
31+
"key": {
32+
"type": "SvelteSpecialDirectiveKey",
33+
"range": [
34+
16,
35+
20
36+
],
37+
"loc": {
38+
"start": {
39+
"line": 1,
40+
"column": 16
41+
},
42+
"end": {
43+
"line": 1,
44+
"column": 20
45+
}
46+
}
47+
},
48+
"expression": {
49+
"type": "Identifier",
50+
"name": "expression",
51+
"range": [
52+
22,
53+
32
54+
],
55+
"loc": {
56+
"start": {
57+
"line": 1,
58+
"column": 22
59+
},
60+
"end": {
61+
"line": 1,
62+
"column": 32
63+
}
64+
}
65+
},
66+
"range": [
67+
16,
68+
34
69+
],
70+
"loc": {
71+
"start": {
72+
"line": 1,
73+
"column": 16
74+
},
75+
"end": {
76+
"line": 1,
77+
"column": 34
78+
}
79+
}
80+
}
81+
],
82+
"selfClosing": true,
83+
"range": [
84+
0,
85+
35
86+
],
87+
"loc": {
88+
"start": {
89+
"line": 1,
90+
"column": 0
91+
},
92+
"end": {
93+
"line": 1,
94+
"column": 35
95+
}
96+
}
97+
},
98+
"children": [],
99+
"endTag": null,
100+
"range": [
101+
0,
102+
35
103+
],
104+
"loc": {
105+
"start": {
106+
"line": 1,
107+
"column": 0
108+
},
109+
"end": {
110+
"line": 1,
111+
"column": 35
112+
}
113+
}
114+
}
115+
],
116+
"sourceType": "module",
117+
"comments": [],
118+
"tokens": [
119+
{
120+
"type": "Punctuator",
121+
"value": "<",
122+
"range": [
123+
0,
124+
1
125+
],
126+
"loc": {
127+
"start": {
128+
"line": 1,
129+
"column": 0
130+
},
131+
"end": {
132+
"line": 1,
133+
"column": 1
134+
}
135+
}
136+
},
137+
{
138+
"type": "HTMLIdentifier",
139+
"value": "svelte:element",
140+
"range": [
141+
1,
142+
15
143+
],
144+
"loc": {
145+
"start": {
146+
"line": 1,
147+
"column": 1
148+
},
149+
"end": {
150+
"line": 1,
151+
"column": 15
152+
}
153+
}
154+
},
155+
{
156+
"type": "HTMLIdentifier",
157+
"value": "this",
158+
"range": [
159+
16,
160+
20
161+
],
162+
"loc": {
163+
"start": {
164+
"line": 1,
165+
"column": 16
166+
},
167+
"end": {
168+
"line": 1,
169+
"column": 20
170+
}
171+
}
172+
},
173+
{
174+
"type": "Punctuator",
175+
"value": "=",
176+
"range": [
177+
20,
178+
21
179+
],
180+
"loc": {
181+
"start": {
182+
"line": 1,
183+
"column": 20
184+
},
185+
"end": {
186+
"line": 1,
187+
"column": 21
188+
}
189+
}
190+
},
191+
{
192+
"type": "Punctuator",
193+
"value": "{",
194+
"range": [
195+
21,
196+
22
197+
],
198+
"loc": {
199+
"start": {
200+
"line": 1,
201+
"column": 21
202+
},
203+
"end": {
204+
"line": 1,
205+
"column": 22
206+
}
207+
}
208+
},
209+
{
210+
"type": "Identifier",
211+
"value": "expression",
212+
"range": [
213+
22,
214+
32
215+
],
216+
"loc": {
217+
"start": {
218+
"line": 1,
219+
"column": 22
220+
},
221+
"end": {
222+
"line": 1,
223+
"column": 32
224+
}
225+
}
226+
},
227+
{
228+
"type": "Punctuator",
229+
"value": "}",
230+
"range": [
231+
32,
232+
33
233+
],
234+
"loc": {
235+
"start": {
236+
"line": 1,
237+
"column": 32
238+
},
239+
"end": {
240+
"line": 1,
241+
"column": 33
242+
}
243+
}
244+
},
245+
{
246+
"type": "Punctuator",
247+
"value": "/",
248+
"range": [
249+
33,
250+
34
251+
],
252+
"loc": {
253+
"start": {
254+
"line": 1,
255+
"column": 33
256+
},
257+
"end": {
258+
"line": 1,
259+
"column": 34
260+
}
261+
}
262+
},
263+
{
264+
"type": "Punctuator",
265+
"value": ">",
266+
"range": [
267+
34,
268+
35
269+
],
270+
"loc": {
271+
"start": {
272+
"line": 1,
273+
"column": 34
274+
},
275+
"end": {
276+
"line": 1,
277+
"column": 35
278+
}
279+
}
280+
}
281+
],
282+
"range": [
283+
0,
284+
35
285+
],
286+
"loc": {
287+
"start": {
288+
"line": 1,
289+
"column": 0
290+
},
291+
"end": {
292+
"line": 1,
293+
"column": 35
294+
}
295+
}
296+
}

0 commit comments

Comments
 (0)