Skip to content

Commit 1c93d5a

Browse files
committed
support for pug (wip)
1 parent cc917d5 commit 1c93d5a

28 files changed

+5468
-84
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
"prettier": "^2.0.5",
9292
"prettier-plugin-pkg": "^0.17.0",
9393
"prettier-plugin-svelte": "^2.5.0",
94+
"pug-lexer": "^5.0.1",
95+
"pug-parser": "^6.0.0",
9496
"semver": "^7.3.5",
9597
"string-replace-loader": "^3.0.3",
9698
"svelte": "^3.46.1",

src/ast/html.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import type ESTree from "estree";
22
import type { BaseNode } from "./base";
33
import type { Token, Comment } from "./common";
4+
import type {
5+
SveltePugAttributePlain,
6+
SveltePugElement,
7+
SveltePugTemplateElement,
8+
SveltePugText,
9+
} from "./pug";
410

511
export type SvelteHTMLNode =
612
| SvelteProgram
@@ -37,7 +43,12 @@ export type SvelteHTMLNode =
3743
/** Node of Svelte program root */
3844
export interface SvelteProgram extends BaseNode {
3945
type: "Program";
40-
body: (SvelteScriptElement | SvelteStyleElement | Child)[];
46+
body: (
47+
| SvelteScriptElement
48+
| SvelteStyleElement
49+
| SveltePugTemplateElement
50+
| Child
51+
)[];
4152
sourceType: "script" | "module";
4253
comments: Comment[];
4354
tokens: Token[];
@@ -87,7 +98,9 @@ export interface SvelteHTMLElement extends BaseSvelteElement {
8798
| SvelteAwaitPendingBlock
8899
| SvelteAwaitThenBlock
89100
| SvelteAwaitCatchBlock
90-
| SvelteKeyBlock;
101+
| SvelteKeyBlock
102+
// Pug
103+
| SveltePugText;
91104
}
92105
/** Node of Svelte component element. */
93106
export interface SvelteComponentElement extends BaseSvelteElement {
@@ -151,13 +164,17 @@ export interface SvelteEndTag extends BaseNode {
151164
export interface SvelteName extends BaseNode {
152165
type: "SvelteName";
153166
name: string;
167+
rawName: string;
154168
parent:
155169
| SvelteElement
156170
| SvelteScriptElement
157171
| SvelteStyleElement
158172
| SvelteAttribute
159173
| SvelteMemberExpressionName
160-
| SvelteDirectiveKey;
174+
| SvelteDirectiveKey
175+
// Pug
176+
| SveltePugAttributePlain
177+
| SveltePugElement;
161178
}
162179

163180
/** Nodes that may be used in component names. The component names separated by dots. */
@@ -194,7 +211,9 @@ export interface SvelteText extends BaseNode {
194211
| SvelteAwaitPendingBlock
195212
| SvelteAwaitThenBlock
196213
| SvelteAwaitCatchBlock
197-
| SvelteKeyBlock;
214+
| SvelteKeyBlock
215+
// Pug
216+
| SveltePugText;
198217
}
199218
/** Node of literal. */
200219
export interface SvelteLiteral extends BaseNode {
@@ -220,7 +239,9 @@ interface BaseSvelteMustacheTag extends BaseNode {
220239
| SvelteAwaitCatchBlock
221240
| SvelteKeyBlock
222241
| SvelteAttribute
223-
| SvelteStyleDirective;
242+
| SvelteStyleDirective
243+
// Pug
244+
| SveltePugText;
224245
}
225246
/** Node of mustache tag. e.g. `{...}``. Like JSXExpressionContainer */
226247
export interface SvelteMustacheTagText extends BaseSvelteMustacheTag {

src/ast/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type { SvelteHTMLNode } from "./html";
22
import type { SvelteScriptNode } from "./script";
3+
import type { SveltePugNode } from "./pug";
34

45
export * from "./common";
56
export * from "./html";
67
export * from "./script";
8+
export * from "./pug";
79

8-
export type SvelteNode = SvelteHTMLNode | SvelteScriptNode;
10+
export type SvelteNode = SvelteHTMLNode | SvelteScriptNode | SveltePugNode;

src/ast/pug.ts

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import type ESTree from "estree";
2+
import type { BaseNode } from "./base";
3+
import type {
4+
SvelteElement,
5+
SvelteEndTag as HTMLEndTag,
6+
SvelteLiteral,
7+
SvelteMemberExpressionName,
8+
SvelteMustacheTag,
9+
SvelteMustacheTagText,
10+
SvelteName,
11+
SvelteProgram,
12+
SvelteStartTag as HTMLStartTag,
13+
SvelteText,
14+
} from "./html";
15+
16+
export type SveltePugNode =
17+
| SveltePugTemplateElement
18+
| SveltePugEachBlock
19+
| SveltePugElement
20+
| SveltePugAttributes
21+
| SveltePugAttribute
22+
| SveltePugAttributeSet
23+
| SveltePugAttributeBlock
24+
| SveltePugSpreadAttribute;
25+
26+
type Child = SveltePugEachBlock | SveltePugElement | SveltePugText;
27+
28+
/** Node of `<template lang="pug">` element. */
29+
export interface SveltePugTemplateElement extends BaseNode {
30+
type: "SveltePugTemplateElement";
31+
name: SvelteName;
32+
startTag: HTMLStartTag;
33+
children: Child[];
34+
endTag: HTMLEndTag | null;
35+
parent: SvelteProgram;
36+
}
37+
38+
/** Node of text. */
39+
export interface SveltePugText extends BaseNode {
40+
type: "SveltePugText";
41+
body: (SvelteElement | SvelteText | SvelteMustacheTag)[];
42+
parent: SveltePugTemplateElement | SveltePugElement | SveltePugEachBlock;
43+
}
44+
45+
/** Node of elements. */
46+
export type SveltePugElement =
47+
| SveltePugHTMLElement
48+
| SveltePugComponentElement
49+
| SveltePugSpecialElement;
50+
51+
/** Node of HTML element. */
52+
export interface SveltePugHTMLElement extends BaseNode {
53+
type: "SveltePugElement";
54+
kind: "html";
55+
name: SvelteName;
56+
attributes: SveltePugAttributes | null;
57+
children: Child[];
58+
parent: SveltePugTemplateElement | SveltePugElement | SveltePugEachBlock;
59+
}
60+
61+
/** Node of Svelte component element. */
62+
export interface SveltePugComponentElement extends BaseNode {
63+
type: "SveltePugElement";
64+
kind: "component";
65+
name: ESTree.Identifier | SvelteMemberExpressionName;
66+
attributes: SveltePugAttributes | null;
67+
children: Child[];
68+
parent: SveltePugTemplateElement | SveltePugElement | SveltePugEachBlock;
69+
}
70+
/** Node of Svelte special component element. e.g. `svelte:window` */
71+
export interface SveltePugSpecialElement extends BaseNode {
72+
type: "SveltePugElement";
73+
kind: "special";
74+
name: SvelteName;
75+
attributes: SveltePugAttributes | null;
76+
children: Child[];
77+
parent: SveltePugTemplateElement | SveltePugElement | SveltePugEachBlock;
78+
}
79+
80+
/** Node of `+each`. */
81+
export interface SveltePugEachBlock extends BaseNode {
82+
type: "SveltePugEachBlock";
83+
expression: ESTree.Expression;
84+
context: ESTree.Pattern;
85+
index: ESTree.Identifier | null;
86+
key: ESTree.Expression | null;
87+
children: Child[];
88+
else: null;
89+
// TODO: support else
90+
// else: SveltePugElseBlockAlone | null;
91+
parent: SveltePugTemplateElement | SveltePugEachBlock | SveltePugElement;
92+
}
93+
/** Node of attributes. */
94+
export interface SveltePugAttributes extends BaseNode {
95+
type: "SveltePugAttributes";
96+
attributes: (
97+
| SveltePugIdAttribute
98+
| SveltePugClassAttribute
99+
| SveltePugAttributeSet
100+
| SveltePugAttributeBlock
101+
)[];
102+
parent: SveltePugElement;
103+
}
104+
105+
interface BaseSveltePugAttribute extends BaseNode {
106+
type: "SveltePugAttribute";
107+
key: SvelteName;
108+
boolean: boolean;
109+
value: (SvelteLiteral | SvelteMustacheTagText)[];
110+
parent: SveltePugAttributes | SveltePugAttributeSet;
111+
}
112+
export type SveltePugAttribute =
113+
| SveltePugAttributePlain
114+
| SveltePugIdAttribute
115+
| SveltePugClassAttribute;
116+
/** Node of attribute. */
117+
export interface SveltePugAttributePlain extends BaseSveltePugAttribute {
118+
kind: "attribute";
119+
parent: SveltePugAttributeSet;
120+
}
121+
/** Node of #id attribute. */
122+
export interface SveltePugIdAttribute extends BaseSveltePugAttribute {
123+
kind: "id";
124+
boolean: false;
125+
parent: SveltePugAttributes;
126+
}
127+
/** Node of .class attribute. */
128+
export interface SveltePugClassAttribute extends BaseSveltePugAttribute {
129+
kind: "class";
130+
boolean: false;
131+
parent: SveltePugAttributes;
132+
}
133+
/** Node of () attributes. */
134+
export interface SveltePugAttributeSet extends BaseNode {
135+
type: "SveltePugAttributeSet";
136+
elements: (SveltePugAttributePlain | SveltePugSpreadAttribute)[];
137+
parent: SveltePugAttributes;
138+
}
139+
/** Node of $attributes(). */
140+
export interface SveltePugAttributeBlock extends BaseNode {
141+
type: "SveltePugAttributeBlock";
142+
parent: SveltePugAttributes;
143+
}
144+
145+
/** Node of spread attribute. */
146+
export interface SveltePugSpreadAttribute extends BaseNode {
147+
type: "SveltePugSpreadAttribute";
148+
argument: ESTree.Expression;
149+
parent: SveltePugAttributeSet;
150+
}

src/context/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,12 @@ export class Context {
339339
)
340340
);
341341
}
342+
343+
public templateBlocks(): (Block & { tag: "template" })[] {
344+
return this.blocks.filter(
345+
(block): block is Block & { tag: "template" } => block.tag === "template"
346+
);
347+
}
342348
}
343349

344350
type Block =

src/context/script-let.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import type {
88
SvelteIfBlock,
99
SvelteName,
1010
SvelteNode,
11+
SveltePugEachBlock,
12+
SveltePugNode,
1113
Token,
1214
} from "../ast";
1315
import type { ESLintExtendedProgram } from "../parser";
@@ -141,7 +143,7 @@ export class ScriptLetContext {
141143

142144
public addExpression<E extends ESTree.Expression>(
143145
expression: E | SvelteName,
144-
parent: SvelteNode,
146+
parent: SvelteNode | SveltePugNode,
145147
typing?: string | null,
146148
...callbacks: ScriptLetCallback<E>[]
147149
): ScriptLetCallback<E>[] {
@@ -311,7 +313,7 @@ export class ScriptLetContext {
311313
expression: ESTree.Expression,
312314
context: ESTree.Pattern,
313315
indexRange: { start: number; end: number } | null,
314-
eachBlock: SvelteEachBlock,
316+
eachBlock: SvelteEachBlock | SveltePugEachBlock,
315317
callback: (
316318
expr: ESTree.Expression,
317319
ctx: ESTree.Pattern,

src/parser/converts/attr.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export function* convertAttributeTokens(
121121
attribute.key = {
122122
type: "SvelteName",
123123
name: attr.key.name,
124+
rawName: attr.key.name,
124125
parent: attribute,
125126
...ctx.getConvertLocation(attr.key),
126127
};
@@ -155,6 +156,7 @@ function convertAttribute(
155156
attribute.key = {
156157
type: "SvelteName",
157158
name: node.name,
159+
rawName: node.name,
158160
parent: attribute,
159161
...ctx.getConvertLocation(keyRange),
160162
};

src/parser/converts/element.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ function convertHTMLElement(
283283
const name: SvelteName = {
284284
type: "SvelteName",
285285
name: node.name,
286+
rawName: node.name,
286287
parent: element,
287288
...ctx.getConvertLocation(openTokenRange),
288289
};
@@ -435,6 +436,7 @@ function convertSpecialElement(
435436
const name: SvelteName = {
436437
type: "SvelteName",
437438
name: node.name,
439+
rawName: node.name,
438440
parent: element,
439441
...ctx.getConvertLocation(openTokenRange),
440442
};
@@ -535,6 +537,7 @@ function convertComponentElement(
535537
property: {
536538
type: "SvelteName",
537539
name,
540+
rawName: name,
538541
parent: null as any,
539542
...ctx.getConvertLocation(range),
540543
},

src/parser/converts/root.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export function convertSvelteRoot(
4949
const name: SvelteName = {
5050
type: "SvelteName",
5151
name: "script",
52+
rawName: "script",
5253
parent: script,
5354
...ctx.getConvertLocation(openTokenRange),
5455
};
@@ -75,6 +76,7 @@ export function convertSvelteRoot(
7576
const name: SvelteName = {
7677
type: "SvelteName",
7778
name: "script",
79+
rawName: "script",
7880
parent: script,
7981
...ctx.getConvertLocation(openTokenRange),
8082
};
@@ -101,6 +103,7 @@ export function convertSvelteRoot(
101103
const name: SvelteName = {
102104
type: "SvelteName",
103105
name: "style",
106+
rawName: "style",
104107
parent: style,
105108
...ctx.getConvertLocation(openTokenRange),
106109
};

src/parser/index.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,19 +179,28 @@ export function parseForESLint(
179179

180180
/** Extract tokens */
181181
function extractTokens(ctx: Context) {
182+
let template = ctx.sourceCode.template;
183+
for (const block of ctx.templateBlocks()) {
184+
if (block.selfClosing) continue;
185+
template =
186+
template.slice(0, block.contentRange[0]) +
187+
ctx.code.slice(...block.contentRange) +
188+
template.slice(block.contentRange[1]);
189+
}
190+
182191
const useRanges = sortNodes([...ctx.tokens, ...ctx.comments]).map(
183192
(t) => t.range
184193
);
185194
let range = useRanges.shift();
186-
for (let index = 0; index < ctx.sourceCode.template.length; index++) {
195+
for (let index = 0; index < template.length; index++) {
187196
while (range && range[1] <= index) {
188197
range = useRanges.shift();
189198
}
190199
if (range && range[0] <= index) {
191200
index = range[1] - 1;
192201
continue;
193202
}
194-
const c = ctx.sourceCode.template[index];
203+
const c = template[index];
195204
if (!c.trim()) {
196205
continue;
197206
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy