Skip to content

Commit 0d387f8

Browse files
authored
Change AST to separate shorthand attributes from attributes (#20)
1 parent 0446b03 commit 0d387f8

File tree

106 files changed

+677
-1019
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+677
-1019
lines changed

src/ast.ts

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,13 @@ export type SvelteNode =
6565
| SvelteAwaitCatchBlock
6666
| SvelteKeyBlock
6767
| SvelteAttribute
68+
| SvelteShorthandAttribute
6869
| SvelteSpreadAttribute
6970
| SvelteDirective
7071
| SvelteHTMLComment
7172
| SvelteReactiveStatement
7273

74+
/** Node of Svelte program root */
7375
export interface SvelteProgram extends BaseNode {
7476
type: "Program"
7577
body: (SvelteScriptElement | SvelteStyleElement | Child)[]
@@ -79,27 +81,50 @@ export interface SvelteProgram extends BaseNode {
7981
parent: null
8082
}
8183

84+
/** Node of elements like HTML element. */
85+
export type SvelteElement =
86+
| SvelteHTMLElement
87+
| SvelteComponentElement
88+
| SvelteSpecialElement
8289
type BaseSvelteElement = BaseNode
8390

91+
/** Node of `<script>` element. */
8492
export interface SvelteScriptElement extends BaseSvelteElement {
8593
type: "SvelteScriptElement"
8694
name: SvelteName
87-
attributes: (SvelteAttribute | SvelteSpreadAttribute | SvelteDirective)[]
95+
attributes: (
96+
| SvelteAttribute
97+
| SvelteShorthandAttribute
98+
| SvelteSpreadAttribute
99+
| SvelteDirective
100+
)[]
88101
body: ESTree.Program["body"]
89102
parent: SvelteProgram
90103
}
104+
/** Node of `<style>` element. */
91105
export interface SvelteStyleElement extends BaseSvelteElement {
92106
type: "SvelteStyleElement"
93107
name: SvelteName
94-
attributes: (SvelteAttribute | SvelteSpreadAttribute | SvelteDirective)[]
108+
attributes: (
109+
| SvelteAttribute
110+
| SvelteShorthandAttribute
111+
| SvelteSpreadAttribute
112+
| SvelteDirective
113+
)[]
95114
children: [SvelteText]
96115
parent: SvelteProgram
97116
}
117+
/** Node of HTML element. */
98118
export interface SvelteHTMLElement extends BaseSvelteElement {
99119
type: "SvelteElement"
100120
kind: "html"
101121
name: SvelteName
102-
attributes: (SvelteAttribute | SvelteSpreadAttribute | SvelteDirective)[]
122+
attributes: (
123+
| SvelteAttribute
124+
| SvelteShorthandAttribute
125+
| SvelteSpreadAttribute
126+
| SvelteDirective
127+
)[]
103128
children: Child[]
104129
parent:
105130
| SvelteProgram
@@ -112,11 +137,17 @@ export interface SvelteHTMLElement extends BaseSvelteElement {
112137
| SvelteAwaitCatchBlock
113138
| SvelteKeyBlock
114139
}
140+
/** Node of Svelte component element. */
115141
export interface SvelteComponentElement extends BaseSvelteElement {
116142
type: "SvelteElement"
117143
kind: "component"
118144
name: ESTree.Identifier
119-
attributes: (SvelteAttribute | SvelteSpreadAttribute | SvelteDirective)[]
145+
attributes: (
146+
| SvelteAttribute
147+
| SvelteShorthandAttribute
148+
| SvelteSpreadAttribute
149+
| SvelteDirective
150+
)[]
120151
children: Child[]
121152
parent:
122153
| SvelteProgram
@@ -129,12 +160,14 @@ export interface SvelteComponentElement extends BaseSvelteElement {
129160
| SvelteAwaitCatchBlock
130161
| SvelteKeyBlock
131162
}
163+
/** Node of Svelte special component element. e.g. `<svelte:window>` */
132164
export interface SvelteSpecialElement extends BaseSvelteElement {
133165
type: "SvelteElement"
134166
kind: "special"
135167
name: SvelteName
136168
attributes: (
137169
| SvelteAttribute
170+
| SvelteShorthandAttribute
138171
| SvelteSpreadAttribute
139172
| SvelteDirective
140173
| SvelteSpecialDirective
@@ -151,15 +184,16 @@ export interface SvelteSpecialElement extends BaseSvelteElement {
151184
| SvelteAwaitCatchBlock
152185
| SvelteKeyBlock
153186
}
154-
export type SvelteElement =
155-
| SvelteHTMLElement
156-
| SvelteComponentElement
157-
| SvelteSpecialElement
158187

188+
/** Node of names. It is used for element names other than components and normal attribute names. */
159189
export interface SvelteName extends BaseNode {
160190
type: "SvelteName"
161191
name: string
162-
parent: SvelteElement | SvelteScriptElement | SvelteStyleElement
192+
parent:
193+
| SvelteElement
194+
| SvelteScriptElement
195+
| SvelteStyleElement
196+
| SvelteAttribute
163197
}
164198

165199
type Child =
@@ -173,6 +207,7 @@ type Child =
173207
| SvelteKeyBlock
174208
| SvelteHTMLComment
175209

210+
/** Node of text line HTML text. */
176211
export interface SvelteText extends BaseNode {
177212
type: "SvelteText"
178213
value: string
@@ -202,15 +237,18 @@ interface BaseSvelteMustacheTag extends BaseNode {
202237
| SvelteKeyBlock
203238
| SvelteAttribute
204239
}
240+
/** Node of mustache tag. e.g. `{...}`, `{@html ...}` */
205241
export interface SvelteMustacheTag extends BaseSvelteMustacheTag {
206242
type: "SvelteMustacheTag"
207243
kind: "text" | "raw"
208244
expression: ESTree.Expression
209245
}
246+
/** Node of debug mustache tag. e.g. `{@debug}` */
210247
export interface SvelteDebugTag extends BaseSvelteMustacheTag {
211248
type: "SvelteDebugTag"
212249
identifiers: ESTree.Identifier[]
213250
}
251+
/** Node of if block. e.g. `{#if}` */
214252
export interface SvelteIfBlock extends BaseNode {
215253
type: "SvelteIfBlock"
216254
elseif: boolean
@@ -228,11 +266,13 @@ export interface SvelteIfBlock extends BaseNode {
228266
| SvelteAwaitCatchBlock
229267
| SvelteKeyBlock
230268
}
269+
/** Node of else block. e.g. `{:else}` */
231270
export interface SvelteElseBlock extends BaseNode {
232271
type: "SvelteElseBlock"
233272
children: Child[]
234273
parent: SvelteIfBlock | SvelteEachBlock
235274
}
275+
/** Node of each block. e.g. `{#each}` */
236276
export interface SvelteEachBlock extends BaseNode {
237277
type: "SvelteEachBlock"
238278
expression: ESTree.Expression
@@ -252,6 +292,7 @@ export interface SvelteEachBlock extends BaseNode {
252292
| SvelteAwaitCatchBlock
253293
| SvelteKeyBlock
254294
}
295+
/** Node of await block. e.g. `{#await}` */
255296
export interface SvelteAwaitBlock extends BaseNode {
256297
type: "SvelteAwaitBlock"
257298
expression: ESTree.Expression
@@ -269,23 +310,27 @@ export interface SvelteAwaitBlock extends BaseNode {
269310
| SvelteAwaitCatchBlock
270311
| SvelteKeyBlock
271312
}
313+
/** Node of await pending block. e.g. `{#await expr} ... {:then}` */
272314
export interface SvelteAwaitPendingBlock extends BaseNode {
273315
type: "SvelteAwaitPendingBlock"
274316
children: Child[]
275317
parent: SvelteAwaitBlock
276318
}
319+
/** Node of await then block. e.g. `{:then}` */
277320
export interface SvelteAwaitThenBlock extends BaseNode {
278321
type: "SvelteAwaitThenBlock"
279322
value: ESTree.Pattern
280323
children: Child[]
281324
parent: SvelteAwaitBlock
282325
}
326+
/** Node of await catch block. e.g. `{:catch}` */
283327
export interface SvelteAwaitCatchBlock extends BaseNode {
284328
type: "SvelteAwaitCatchBlock"
285329
error: ESTree.Pattern
286330
children: Child[]
287331
parent: SvelteAwaitBlock
288332
}
333+
/** Node of key block. e.g. `{#key}` */
289334
export interface SvelteKeyBlock extends BaseNode {
290335
type: "SvelteKeyBlock"
291336
expression: ESTree.Expression
@@ -301,6 +346,7 @@ export interface SvelteKeyBlock extends BaseNode {
301346
| SvelteAwaitCatchBlock
302347
| SvelteKeyBlock
303348
}
349+
/** Node of HTML comment. */
304350
export interface SvelteHTMLComment extends BaseNode {
305351
type: "SvelteHTMLComment"
306352
value: string
@@ -315,32 +361,38 @@ export interface SvelteHTMLComment extends BaseNode {
315361
| SvelteAwaitCatchBlock
316362
| SvelteKeyBlock
317363
}
318-
319-
export interface SvelteAttributeNonShorthand extends BaseNode {
364+
/** Node of HTML comment. */
365+
export interface SvelteAttribute extends BaseNode {
320366
type: "SvelteAttribute"
321-
key: ESTree.Identifier
322-
shorthand: false
367+
key: SvelteName
323368
boolean: boolean
324369
value: (SvelteText | (SvelteMustacheTag & { kind: "text" }))[]
325370
parent: SvelteElement | SvelteScriptElement | SvelteStyleElement
326371
}
327-
export interface SvelteAttributeShorthand extends BaseNode {
328-
type: "SvelteAttribute"
372+
/** Node of shorthand attribute. e.g. `<img {src}>` */
373+
export interface SvelteShorthandAttribute extends BaseNode {
374+
type: "SvelteShorthandAttribute"
329375
key: ESTree.Identifier
330-
shorthand: true
331-
boolean: boolean
332-
value: [ESTree.Identifier]
376+
value: ESTree.Identifier
333377
parent: SvelteElement | SvelteScriptElement | SvelteStyleElement
334378
}
335-
export type SvelteAttribute =
336-
| SvelteAttributeNonShorthand
337-
| SvelteAttributeShorthand
379+
/** Node of spread attribute. e.g. `<Info {...pkg}/>` */
338380
export interface SvelteSpreadAttribute extends BaseNode {
339381
type: "SvelteSpreadAttribute"
340382
expression: ESTree.Expression
341383
parent: SvelteElement | SvelteScriptElement | SvelteStyleElement
342384
}
343385

386+
/** Node of directive. e.g. `<input bind:value />` */
387+
export type SvelteDirective =
388+
| SvelteActionDirective
389+
| SvelteAnimationDirective
390+
| SvelteBindingDirective
391+
| SvelteClassDirective
392+
| SvelteEventHandlerDirective
393+
| SvelteLetDirective
394+
| SvelteRefDirective
395+
| SvelteTransitionDirective
344396
interface BaseSvelteDirective extends BaseNode {
345397
type: "SvelteDirective"
346398
name: ESTree.Identifier
@@ -389,16 +441,7 @@ export interface SvelteSpecialDirective extends BaseNode {
389441
parent: SvelteSpecialElement
390442
}
391443

392-
export type SvelteDirective =
393-
| SvelteActionDirective
394-
| SvelteAnimationDirective
395-
| SvelteBindingDirective
396-
| SvelteClassDirective
397-
| SvelteEventHandlerDirective
398-
| SvelteLetDirective
399-
| SvelteRefDirective
400-
| SvelteTransitionDirective
401-
444+
/** Node of `$` statement. */
402445
export interface SvelteReactiveStatement extends BaseNode {
403446
type: "SvelteReactiveStatement"
404447
label: ESTree.Identifier & { name: "$" }

src/parser/converts/attr.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type {
22
SvelteActionDirective,
33
SvelteAnimationDirective,
44
SvelteAttribute,
5-
SvelteAttributeShorthand,
5+
SvelteShorthandAttribute,
66
SvelteBindingDirective,
77
SvelteClassDirective,
88
SvelteDirective,
@@ -33,7 +33,12 @@ export function* convertAttributes(
3333
attributes: SvAST.AttributeOrDirective[],
3434
parent: SvelteElement | SvelteScriptElement | SvelteStyleElement,
3535
ctx: Context,
36-
): IterableIterator<SvelteAttribute | SvelteSpreadAttribute | SvelteDirective> {
36+
): IterableIterator<
37+
| SvelteAttribute
38+
| SvelteShorthandAttribute
39+
| SvelteSpreadAttribute
40+
| SvelteDirective
41+
> {
3742
for (const attr of attributes) {
3843
if (attr.type === "Attribute") {
3944
yield convertAttribute(attr, parent, ctx)
@@ -87,10 +92,9 @@ function convertAttribute(
8792
node: SvAST.Attribute,
8893
parent: SvelteAttribute["parent"],
8994
ctx: Context,
90-
): SvelteAttribute {
95+
): SvelteAttribute | SvelteShorthandAttribute {
9196
const attribute: SvelteAttribute = {
9297
type: "SvelteAttribute",
93-
shorthand: false,
9498
boolean: false,
9599
key: null as any,
96100
value: [],
@@ -100,8 +104,9 @@ function convertAttribute(
100104
const keyStart = ctx.code.indexOf(node.name, node.start)
101105
const keyRange = { start: keyStart, end: keyStart + node.name.length }
102106
attribute.key = {
103-
type: "Identifier",
107+
type: "SvelteName",
104108
name: node.name,
109+
parent: attribute,
105110
...ctx.getConvertLocation(keyRange),
106111
}
107112
ctx.addToken("HTMLIdentifier", keyRange)
@@ -112,12 +117,20 @@ function convertAttribute(
112117
}
113118
for (const v of node.value) {
114119
if (v.type === "AttributeShorthand") {
115-
const sAttr: SvelteAttributeShorthand = {
116-
...attribute,
117-
shorthand: true,
118-
value: [attribute.key],
120+
const key: ESTree.Identifier = {
121+
...attribute.key,
122+
type: "Identifier",
119123
}
120-
analyzeExpressionScope(attribute.key, ctx)
124+
const sAttr: SvelteShorthandAttribute = {
125+
type: "SvelteShorthandAttribute",
126+
key,
127+
value: key,
128+
parent,
129+
loc: attribute.loc,
130+
range: attribute.range,
131+
}
132+
;(key as any).parent = sAttr
133+
analyzeExpressionScope(sAttr.key, ctx)
121134
return sAttr
122135
}
123136
if (v.type === "Text") {

src/visitor-keys.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const svelteKeys: SvelteKeysType = {
3333
SvelteAwaitCatchBlock: ["error", "children"],
3434
SvelteKeyBlock: ["expression", "children"],
3535
SvelteAttribute: ["key", "value"],
36+
SvelteShorthandAttribute: ["key", "value"],
3637
SvelteSpreadAttribute: ["expression"],
3738
SvelteDirective: ["expression"],
3839
SvelteReactiveStatement: ["label", "body"],

tests/fixtures/parser/ast/blog/write-less-code01-output.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,9 @@
245245
"attributes": [
246246
{
247247
"type": "SvelteAttribute",
248-
"shorthand": false,
249248
"boolean": false,
250249
"key": {
251-
"type": "Identifier",
250+
"type": "SvelteName",
252251
"name": "type",
253252
"range": [
254253
51,
@@ -416,10 +415,9 @@
416415
"attributes": [
417416
{
418417
"type": "SvelteAttribute",
419-
"shorthand": false,
420418
"boolean": false,
421419
"key": {
422-
"type": "Identifier",
420+
"type": "SvelteName",
423421
"name": "type",
424422
"range": [
425423
88,

tests/fixtures/parser/ast/docs/component-format/02-script-context-module/01-output.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@
2424
"attributes": [
2525
{
2626
"type": "SvelteAttribute",
27-
"shorthand": false,
2827
"boolean": false,
2928
"key": {
30-
"type": "Identifier",
29+
"type": "SvelteName",
3130
"name": "context",
3231
"range": [
3332
8,

0 commit comments

Comments
 (0)