fix: correctly backport `svelte:element` to old AST (#11917)

Both `<svelte:element this="div">` and `<svelte:element this={"div"}>` were backported as `tag: "div"` for the old AST. That's wrong because the latter should result in `tag: { type: 'Literal', .. }`. Fixing this makes all the tests in prettier-plugin-svelte pass with Svelte 5.

Also cleaned up a bit of code in the parser.
pull/11899/head
Simon H 1 year ago committed by GitHub
parent b1cbfc3d38
commit 6efd9d6f44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: correctly backport `svelte:element` to old AST

@ -478,7 +478,11 @@ export function convert(source, ast) {
SvelteElement(node, { visit }) { SvelteElement(node, { visit }) {
/** @type {import('estree').Expression | string} */ /** @type {import('estree').Expression | string} */
let tag = node.tag; let tag = node.tag;
if (tag.type === 'Literal' && typeof tag.value === 'string') { if (
tag.type === 'Literal' &&
typeof tag.value === 'string' &&
source[/** @type {number} */ (node.tag.start) - 1] !== '{'
) {
tag = tag.value; tag = tag.value;
} }

@ -7,7 +7,6 @@ import full_char_code_at from './utils/full_char_code_at.js';
import * as e from '../../errors.js'; import * as e from '../../errors.js';
import { create_fragment } from './utils/create.js'; import { create_fragment } from './utils/create.js';
import read_options from './read/options.js'; import read_options from './read/options.js';
import { locator } from '../../state.js';
const regex_position_indicator = / \(\d+:\d+\)$/; const regex_position_indicator = / \(\d+:\d+\)$/;

@ -14,7 +14,7 @@ const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
/** Invalid attribute characters if the attribute is not surrounded by quotes */ /** Invalid attribute characters if the attribute is not surrounded by quotes */
const regex_starts_with_invalid_attr_value = /^(\/>|[\s"'=<>`])/; const regex_starts_with_invalid_attr_value = /^(\/>|[\s"'=<>`])/;
/** @type {Map<string, import('#compiler').SvelteNode['type']>} */ /** @type {Map<string, import('#compiler').ElementLike['type']>} */
const root_only_meta_tags = new Map([ const root_only_meta_tags = new Map([
['svelte:head', 'SvelteHead'], ['svelte:head', 'SvelteHead'],
['svelte:options', 'SvelteOptions'], ['svelte:options', 'SvelteOptions'],
@ -23,7 +23,7 @@ const root_only_meta_tags = new Map([
['svelte:body', 'SvelteBody'] ['svelte:body', 'SvelteBody']
]); ]);
/** @type {Map<string, import('#compiler').SvelteNode['type']>} */ /** @type {Map<string, import('#compiler').ElementLike['type']>} */
const meta_tags = new Map([ const meta_tags = new Map([
...root_only_meta_tags, ...root_only_meta_tags,
['svelte:element', 'SvelteElement'], ['svelte:element', 'SvelteElement'],
@ -132,11 +132,10 @@ export default function tag(parser) {
: 'RegularElement'; : 'RegularElement';
/** @type {import('#compiler').ElementLike} */ /** @type {import('#compiler').ElementLike} */
// @ts-expect-error TODO can't figure out this error
const element = const element =
type === 'RegularElement' type === 'RegularElement'
? { ? {
type: /** @type {import('#compiler').ElementLike['type']} */ (type), type: type,
start, start,
end: -1, end: -1,
name, name,
@ -144,12 +143,14 @@ export default function tag(parser) {
fragment: create_fragment(true), fragment: create_fragment(true),
metadata: { metadata: {
svg: false, svg: false,
mathml: false,
scoped: false,
has_spread: false has_spread: false
}, },
parent: null parent: null
} }
: { : /** @type {import('#compiler').ElementLike} */ ({
type: /** @type {import('#compiler').ElementLike['type']} */ (type), type,
start, start,
end: -1, end: -1,
name, name,
@ -159,7 +160,7 @@ export default function tag(parser) {
metadata: { metadata: {
svg: false svg: false
} }
}; });
parser.allow_whitespace(); parser.allow_whitespace();

@ -1,2 +1,7 @@
<svelte:element this="div"></svelte:element>
<!-- prettier-ignore -->
<svelte:element this='div'></svelte:element>
<svelte:element this={"div"}></svelte:element> <svelte:element this={"div"}></svelte:element>
<!-- prettier-ignore -->
<svelte:element this={'div'}></svelte:element>
<svelte:element this={"div"} class="foo"></svelte:element> <svelte:element this={"div"} class="foo"></svelte:element>

@ -2,40 +2,164 @@
"html": { "html": {
"type": "Fragment", "type": "Fragment",
"start": 0, "start": 0,
"end": 105, "end": 292,
"children": [ "children": [
{ {
"type": "Element", "type": "Element",
"name": "svelte:element", "name": "svelte:element",
"start": 0, "start": 0,
"end": 46, "end": 44,
"tag": "div", "tag": "div",
"attributes": [], "attributes": [],
"children": [] "children": []
}, },
{ {
"type": "Text", "type": "Text",
"start": 46, "start": 44,
"end": 47, "end": 45,
"raw": "\n",
"data": "\n"
},
{
"type": "Comment",
"start": 45,
"end": 69,
"data": " prettier-ignore ",
"ignores": []
},
{
"type": "Text",
"start": 69,
"end": 70,
"raw": "\n", "raw": "\n",
"data": "\n" "data": "\n"
}, },
{ {
"type": "Element", "type": "Element",
"name": "svelte:element", "name": "svelte:element",
"start": 47, "start": 70,
"end": 105, "end": 114,
"tag": "div", "tag": "div",
"attributes": [],
"children": []
},
{
"type": "Text",
"start": 114,
"end": 115,
"raw": "\n",
"data": "\n"
},
{
"type": "Element",
"name": "svelte:element",
"start": 115,
"end": 161,
"tag": {
"type": "Literal",
"start": 137,
"end": 142,
"loc": {
"start": {
"line": 4,
"column": 22
},
"end": {
"line": 4,
"column": 27
}
},
"value": "div",
"raw": "\"div\""
},
"attributes": [],
"children": []
},
{
"type": "Text",
"start": 161,
"end": 162,
"raw": "\n",
"data": "\n"
},
{
"type": "Comment",
"start": 162,
"end": 186,
"data": " prettier-ignore ",
"ignores": []
},
{
"type": "Text",
"start": 186,
"end": 187,
"raw": "\n",
"data": "\n"
},
{
"type": "Element",
"name": "svelte:element",
"start": 187,
"end": 233,
"tag": {
"type": "Literal",
"start": 209,
"end": 214,
"loc": {
"start": {
"line": 6,
"column": 22
},
"end": {
"line": 6,
"column": 27
}
},
"value": "div",
"raw": "'div'"
},
"attributes": [],
"children": []
},
{
"type": "Text",
"start": 233,
"end": 234,
"raw": "\n",
"data": "\n"
},
{
"type": "Element",
"name": "svelte:element",
"start": 234,
"end": 292,
"tag": {
"type": "Literal",
"start": 256,
"end": 261,
"loc": {
"start": {
"line": 7,
"column": 22
},
"end": {
"line": 7,
"column": 27
}
},
"value": "div",
"raw": "\"div\""
},
"attributes": [ "attributes": [
{ {
"type": "Attribute", "type": "Attribute",
"start": 76, "start": 263,
"end": 87, "end": 274,
"name": "class", "name": "class",
"value": [ "value": [
{ {
"start": 83, "start": 270,
"end": 86, "end": 273,
"type": "Text", "type": "Text",
"raw": "foo", "raw": "foo",
"data": "foo" "data": "foo"

Loading…
Cancel
Save