Skip to content

Commit c87e7a6

Browse files
committed
fix: changed so that if Compiler.SvelteOptions does not have __raw__ property, we parse it ourselves
1 parent aea9727 commit c87e7a6

File tree

8 files changed

+798
-352
lines changed

8 files changed

+798
-352
lines changed

Diff for: src/context/index.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import type * as SvAST from "../parser/svelte-ast-types";
1515
import type * as Compiler from "svelte/compiler";
1616
import { ScriptLetContext } from "./script-let";
1717
import { LetDirectiveCollections } from "./let-directive-collection";
18-
import type { AttributeToken } from "../parser/html";
1918
import { parseAttributes } from "../parser/html";
2019
import { sortedLastIndex } from "../utils";
2120
import {
@@ -181,8 +180,16 @@ export class Context {
181180
if (block.selfClosing) {
182181
continue;
183182
}
184-
const lang = block.attrs.find((attr) => attr.key.name === "lang");
185-
if (!lang || !lang.value || lang.value.value === "html") {
183+
const lang = block.attrs.find((attr) => attr.name === "lang");
184+
if (!lang || !Array.isArray(lang.value)) {
185+
continue;
186+
}
187+
const langValue = lang.value[0];
188+
if (
189+
!langValue ||
190+
langValue.type !== "Text" ||
191+
langValue.data === "html"
192+
) {
186193
continue;
187194
}
188195
}
@@ -212,7 +219,13 @@ export class Context {
212219
spaces.slice(start, block.contentRange[0]) +
213220
code.slice(...block.contentRange);
214221
for (const attr of block.attrs) {
215-
scriptAttrs[attr.key.name] = attr.value?.value;
222+
if (Array.isArray(attr.value)) {
223+
const attrValue = attr.value[0];
224+
scriptAttrs[attr.name] =
225+
attrValue && attrValue.type === "Text"
226+
? attrValue.data
227+
: undefined;
228+
}
216229
}
217230
} else {
218231
scriptCode += spaces.slice(start, block.contentRange[1]);
@@ -338,7 +351,7 @@ type Block =
338351
| {
339352
tag: "script" | "style" | "template";
340353
originalTag: string;
341-
attrs: AttributeToken[];
354+
attrs: Compiler.Attribute[];
342355
selfClosing?: false;
343356
contentRange: [number, number];
344357
startTagRange: [number, number];
@@ -349,7 +362,7 @@ type Block =
349362
type SelfClosingBlock = {
350363
tag: "script" | "style" | "template";
351364
originalTag: string;
352-
attrs: AttributeToken[];
365+
attrs: Compiler.Attribute[];
353366
selfClosing: true;
354367
startTagRange: [number, number];
355368
};
@@ -371,7 +384,7 @@ function* extractBlocks(code: string): IterableIterator<Block> {
371384

372385
const lowerTag = tag.toLowerCase() as "script" | "style" | "template";
373386

374-
let attrs: AttributeToken[] = [];
387+
let attrs: Compiler.Attribute[] = [];
375388
if (!nextChar.trim()) {
376389
const attrsData = parseAttributes(code, startTagOpenRe.lastIndex);
377390
attrs = attrsData.attributes;

Diff for: src/parser/compat.ts

+49-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import type ESTree from "estree";
33
import type * as SvAST from "./svelte-ast-types";
44
import type * as Compiler from "svelte/compiler";
5+
import { parseAttributes } from "./html";
56

67
export type Child =
78
| Compiler.Text
@@ -30,8 +31,18 @@ export function getModuleFromRoot(
3031
}
3132
export function getOptionsFromRoot(
3233
svelteAst: Compiler.Root | SvAST.AstLegacy,
34+
code: string,
3335
): Compiler.SvelteOptionsRaw | null {
34-
return (svelteAst as any).options?.__raw__ ?? null;
36+
const root = svelteAst as Compiler.Root;
37+
if (root.options) {
38+
if ((root.options as any).__raw__) {
39+
return (root.options as any).__raw__;
40+
}
41+
// If there is no `__raw__` property in the `SvelteOptions` node,
42+
// we will parse `<svelte:options>` ourselves.
43+
return parseSvelteOptions(root.options, code);
44+
}
45+
return null;
3546
}
3647

3748
export function getChildren(
@@ -228,3 +239,40 @@ export function getDeclaratorFromConstTag(
228239
(node as SvAST.ConstTag).expression
229240
);
230241
}
242+
243+
function parseSvelteOptions(
244+
options: Compiler.SvelteOptions,
245+
code: string,
246+
): Compiler.SvelteOptionsRaw {
247+
const { start, end } = options;
248+
const nameEndName = start + "<svelte:options".length;
249+
const { attributes, index: tagEndIndex } = parseAttributes(
250+
code,
251+
nameEndName + 1,
252+
);
253+
const fragment: Compiler.Fragment = {
254+
type: "Fragment",
255+
nodes: [],
256+
transparent: true,
257+
};
258+
if (code.startsWith(">", tagEndIndex)) {
259+
const childEndIndex = code.indexOf("</svelte:options", tagEndIndex);
260+
fragment.nodes.push({
261+
type: "Text",
262+
data: code.slice(tagEndIndex + 1, childEndIndex),
263+
start: tagEndIndex + 1,
264+
end: childEndIndex,
265+
raw: code.slice(tagEndIndex + 1, childEndIndex),
266+
parent: fragment,
267+
});
268+
}
269+
return {
270+
type: "SvelteOptions",
271+
name: "svelte:options",
272+
attributes,
273+
fragment,
274+
start,
275+
end,
276+
parent: null as any,
277+
};
278+
}

Diff for: src/parser/converts/attr.ts

+1-41
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,9 @@ import type * as SvAST from "../svelte-ast-types";
2727
import type * as Compiler from "svelte/compiler";
2828
import { getWithLoc, indexOf } from "./common";
2929
import { convertMustacheTag } from "./mustache";
30-
import {
31-
convertAttributeValueTokenToLiteral,
32-
convertTextToLiteral,
33-
} from "./text";
30+
import { convertTextToLiteral } from "./text";
3431
import { ParseError } from "../../errors";
3532
import type { ScriptLetCallback } from "../../context/script-let";
36-
import type { AttributeToken } from "../html";
3733
import { svelteVersion } from "../svelte-version";
3834
import { hasTypeInfo } from "../../utils";
3935
import { getModifiers } from "../compat";
@@ -125,42 +121,6 @@ export function* convertAttributes(
125121
}
126122
}
127123

128-
/** Convert for attribute tokens */
129-
export function* convertAttributeTokens(
130-
attributes: AttributeToken[],
131-
parent: SvelteStartTag,
132-
ctx: Context,
133-
): IterableIterator<SvelteAttribute> {
134-
for (const attr of attributes) {
135-
const attribute: SvelteAttribute = {
136-
type: "SvelteAttribute",
137-
boolean: false,
138-
key: null as any,
139-
value: [],
140-
parent,
141-
...ctx.getConvertLocation({
142-
start: attr.key.start,
143-
end: attr.value?.end ?? attr.key.end,
144-
}),
145-
};
146-
attribute.key = {
147-
type: "SvelteName",
148-
name: attr.key.name,
149-
parent: attribute,
150-
...ctx.getConvertLocation(attr.key),
151-
};
152-
ctx.addToken("HTMLIdentifier", attr.key);
153-
if (attr.value == null) {
154-
attribute.boolean = true;
155-
} else {
156-
attribute.value.push(
157-
convertAttributeValueTokenToLiteral(attr.value, attribute, ctx),
158-
);
159-
}
160-
yield attribute;
161-
}
162-
}
163-
164124
/** Convert for Attribute */
165125
function convertAttribute(
166126
node: SvAST.Attribute | Compiler.Attribute,

Diff for: src/parser/converts/root.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
import {} from "./common";
1010
import type { Context } from "../../context";
1111
import { convertChildren, extractElementTags } from "./element";
12-
import { convertAttributeTokens } from "./attr";
12+
import { convertAttributes } from "./attr";
1313
import type { Scope } from "eslint-scope";
1414
import {
1515
getChildren,
@@ -39,7 +39,7 @@ export function convertSvelteRoot(
3939
const fragment = getFragmentFromRoot(svelteAst);
4040
if (fragment) {
4141
let children = getChildren(fragment);
42-
const options = getOptionsFromRoot(svelteAst);
42+
const options = getOptionsFromRoot(svelteAst, ctx.code);
4343
if (options) {
4444
children = [...children];
4545
if (
@@ -202,7 +202,7 @@ function extractAttributes(
202202
const block = ctx.findBlock(element);
203203
if (block) {
204204
element.startTag.attributes.push(
205-
...convertAttributeTokens(block.attrs, element.startTag, ctx),
205+
...convertAttributes(block.attrs, element.startTag, ctx),
206206
);
207207
}
208208
}

Diff for: src/parser/converts/text.ts

-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { SvelteLiteral, SvelteText } from "../../ast";
22
import type { Context } from "../../context";
3-
import type { AttributeValueToken } from "../html";
43
import type * as SvAST from "../svelte-ast-types";
54
/** Convert for Text */
65
export function convertText(
@@ -34,25 +33,6 @@ export function convertTextToLiteral(
3433
return text;
3534
}
3635

37-
/** Convert for AttributeValueToken to Literal */
38-
export function convertAttributeValueTokenToLiteral(
39-
node: AttributeValueToken,
40-
parent: SvelteLiteral["parent"],
41-
ctx: Context,
42-
): SvelteLiteral {
43-
const valueLoc = node.quote
44-
? { start: node.start + 1, end: node.end - 1 }
45-
: node;
46-
const text: SvelteLiteral = {
47-
type: "SvelteLiteral",
48-
value: node.value,
49-
parent,
50-
...ctx.getConvertLocation(valueLoc),
51-
};
52-
extractTextTokens(valueLoc, ctx);
53-
return text;
54-
}
55-
5636
/** Extract tokens */
5737
function extractTextTokens(
5838
node: { start: number; end: number },

0 commit comments

Comments
 (0)