Skip to content

Commit

Permalink
fix: changed so that if Compiler.SvelteOptions does not have __raw__ …
Browse files Browse the repository at this point in the history
…property, we parse it ourselves
  • Loading branch information
ota-meshi committed Dec 3, 2023
1 parent 9e54835 commit 6ee516a
Show file tree
Hide file tree
Showing 8 changed files with 798 additions and 352 deletions.
27 changes: 20 additions & 7 deletions src/context/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import type * as SvAST from "../parser/svelte-ast-types";
import type * as Compiler from "svelte/compiler";
import { ScriptLetContext } from "./script-let";
import { LetDirectiveCollections } from "./let-directive-collection";
import type { AttributeToken } from "../parser/html";
import { parseAttributes } from "../parser/html";
import { sortedLastIndex } from "../utils";
import {
Expand Down Expand Up @@ -181,8 +180,16 @@ export class Context {
if (block.selfClosing) {
continue;
}
const lang = block.attrs.find((attr) => attr.key.name === "lang");
if (!lang || !lang.value || lang.value.value === "html") {
const lang = block.attrs.find((attr) => attr.name === "lang");
if (!lang || !Array.isArray(lang.value)) {
continue;
}
const langValue = lang.value[0];
if (
!langValue ||
langValue.type !== "Text" ||
langValue.data === "html"
) {
continue;
}
}
Expand Down Expand Up @@ -212,7 +219,13 @@ export class Context {
spaces.slice(start, block.contentRange[0]) +
code.slice(...block.contentRange);
for (const attr of block.attrs) {
scriptAttrs[attr.key.name] = attr.value?.value;
if (Array.isArray(attr.value)) {
const attrValue = attr.value[0];
scriptAttrs[attr.name] =
attrValue && attrValue.type === "Text"
? attrValue.data
: undefined;
}
}
} else {
scriptCode += spaces.slice(start, block.contentRange[1]);
Expand Down Expand Up @@ -338,7 +351,7 @@ type Block =
| {
tag: "script" | "style" | "template";
originalTag: string;
attrs: AttributeToken[];
attrs: Compiler.Attribute[];
selfClosing?: false;
contentRange: [number, number];
startTagRange: [number, number];
Expand All @@ -349,7 +362,7 @@ type Block =
type SelfClosingBlock = {
tag: "script" | "style" | "template";
originalTag: string;
attrs: AttributeToken[];
attrs: Compiler.Attribute[];
selfClosing: true;
startTagRange: [number, number];
};
Expand All @@ -371,7 +384,7 @@ function* extractBlocks(code: string): IterableIterator<Block> {

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

let attrs: AttributeToken[] = [];
let attrs: Compiler.Attribute[] = [];
if (!nextChar.trim()) {
const attrsData = parseAttributes(code, startTagOpenRe.lastIndex);
attrs = attrsData.attributes;
Expand Down
50 changes: 49 additions & 1 deletion src/parser/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import type ESTree from "estree";
import type * as SvAST from "./svelte-ast-types";
import type * as Compiler from "svelte/compiler";
import { parseAttributes } from "./html";

export type Child =
| Compiler.Text
Expand Down Expand Up @@ -30,8 +31,18 @@ export function getModuleFromRoot(
}
export function getOptionsFromRoot(
svelteAst: Compiler.Root | SvAST.AstLegacy,
code: string,
): Compiler.SvelteOptionsRaw | null {
return (svelteAst as any).options?.__raw__ ?? null;
const root = svelteAst as Compiler.Root;
if (root.options) {
if ((root.options as any).__raw__) {
return (root.options as any).__raw__;
}
// If there is no `__raw__` property in the `SvelteOptions` node,
// we will parse `<svelte:options>` ourselves.
return parseSvelteOptions(root.options, code);
}
return null;
}

export function getChildren(
Expand Down Expand Up @@ -228,3 +239,40 @@ export function getDeclaratorFromConstTag(
(node as SvAST.ConstTag).expression
);
}

function parseSvelteOptions(
options: Compiler.SvelteOptions,
code: string,
): Compiler.SvelteOptionsRaw {
const { start, end } = options;
const nameEndName = start + "<svelte:options".length;
const { attributes, index: tagEndIndex } = parseAttributes(
code,
nameEndName + 1,
);
const fragment: Compiler.Fragment = {
type: "Fragment",
nodes: [],
transparent: true,
};
if (code.startsWith(">", tagEndIndex)) {
const childEndIndex = code.indexOf("</svelte:options", tagEndIndex);
fragment.nodes.push({
type: "Text",
data: code.slice(tagEndIndex + 1, childEndIndex),
start: tagEndIndex + 1,
end: childEndIndex,
raw: code.slice(tagEndIndex + 1, childEndIndex),
parent: fragment,
});
}
return {
type: "SvelteOptions",
name: "svelte:options",
attributes,
fragment,
start,
end,
parent: null as any,
};
}
42 changes: 1 addition & 41 deletions src/parser/converts/attr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,9 @@ import type * as SvAST from "../svelte-ast-types";
import type * as Compiler from "svelte/compiler";
import { getWithLoc, indexOf } from "./common";
import { convertMustacheTag } from "./mustache";
import {
convertAttributeValueTokenToLiteral,
convertTextToLiteral,
} from "./text";
import { convertTextToLiteral } from "./text";
import { ParseError } from "../../errors";
import type { ScriptLetCallback } from "../../context/script-let";
import type { AttributeToken } from "../html";
import { svelteVersion } from "../svelte-version";
import { hasTypeInfo } from "../../utils";
import { getModifiers } from "../compat";
Expand Down Expand Up @@ -125,42 +121,6 @@ export function* convertAttributes(
}
}

/** Convert for attribute tokens */
export function* convertAttributeTokens(
attributes: AttributeToken[],
parent: SvelteStartTag,
ctx: Context,
): IterableIterator<SvelteAttribute> {
for (const attr of attributes) {
const attribute: SvelteAttribute = {
type: "SvelteAttribute",
boolean: false,
key: null as any,
value: [],
parent,
...ctx.getConvertLocation({
start: attr.key.start,
end: attr.value?.end ?? attr.key.end,
}),
};
attribute.key = {
type: "SvelteName",
name: attr.key.name,
parent: attribute,
...ctx.getConvertLocation(attr.key),
};
ctx.addToken("HTMLIdentifier", attr.key);
if (attr.value == null) {
attribute.boolean = true;
} else {
attribute.value.push(
convertAttributeValueTokenToLiteral(attr.value, attribute, ctx),
);
}
yield attribute;
}
}

/** Convert for Attribute */
function convertAttribute(
node: SvAST.Attribute | Compiler.Attribute,
Expand Down
6 changes: 3 additions & 3 deletions src/parser/converts/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
import {} from "./common";
import type { Context } from "../../context";
import { convertChildren, extractElementTags } from "./element";
import { convertAttributeTokens } from "./attr";
import { convertAttributes } from "./attr";
import type { Scope } from "eslint-scope";
import {
getChildren,
Expand Down Expand Up @@ -39,7 +39,7 @@ export function convertSvelteRoot(
const fragment = getFragmentFromRoot(svelteAst);
if (fragment) {
let children = getChildren(fragment);
const options = getOptionsFromRoot(svelteAst);
const options = getOptionsFromRoot(svelteAst, ctx.code);
if (options) {
children = [...children];
if (
Expand Down Expand Up @@ -202,7 +202,7 @@ function extractAttributes(
const block = ctx.findBlock(element);
if (block) {
element.startTag.attributes.push(
...convertAttributeTokens(block.attrs, element.startTag, ctx),
...convertAttributes(block.attrs, element.startTag, ctx),
);
}
}
20 changes: 0 additions & 20 deletions src/parser/converts/text.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { SvelteLiteral, SvelteText } from "../../ast";
import type { Context } from "../../context";
import type { AttributeValueToken } from "../html";
import type * as SvAST from "../svelte-ast-types";
/** Convert for Text */
export function convertText(
Expand Down Expand Up @@ -34,25 +33,6 @@ export function convertTextToLiteral(
return text;
}

/** Convert for AttributeValueToken to Literal */
export function convertAttributeValueTokenToLiteral(
node: AttributeValueToken,
parent: SvelteLiteral["parent"],
ctx: Context,
): SvelteLiteral {
const valueLoc = node.quote
? { start: node.start + 1, end: node.end - 1 }
: node;
const text: SvelteLiteral = {
type: "SvelteLiteral",
value: node.value,
parent,
...ctx.getConvertLocation(valueLoc),
};
extractTextTokens(valueLoc, ctx);
return text;
}

/** Extract tokens */
function extractTextTokens(
node: { start: number; end: number },
Expand Down

0 comments on commit 6ee516a

Please sign in to comment.