From 67bf7a80673ce9e1a6f5f5e7ab70be2b89a05690 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Mon, 8 Jul 2024 18:46:47 +0900 Subject: [PATCH] fix: correct start of `{:else if}` and `{:else}` (#12043) The modern AST is an opportunity to tweak things. In the old AST, the start of else (if) branches was the content, now it's the opening bracket, which makes more sense. --- .changeset/cold-teachers-turn.md | 5 + packages/svelte/src/compiler/legacy.js | 3 +- .../src/compiler/phases/1-parse/state/tag.js | 2 +- .../samples/if-block-else/input.svelte | 5 + .../samples/if-block-else/output.json | 116 ++++++++++ .../samples/if-block-elseif/input.svelte | 5 + .../samples/if-block-elseif/output.json | 211 ++++++++++++++++++ .../samples/if-block/input.svelte | 1 + .../samples/if-block/output.json | 50 +++++ 9 files changed, 396 insertions(+), 2 deletions(-) create mode 100644 .changeset/cold-teachers-turn.md create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-else/output.json create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json create mode 100644 packages/svelte/tests/parser-modern/samples/if-block/input.svelte create mode 100644 packages/svelte/tests/parser-modern/samples/if-block/output.json diff --git a/.changeset/cold-teachers-turn.md b/.changeset/cold-teachers-turn.md new file mode 100644 index 0000000000..e86ffbcdfe --- /dev/null +++ b/.changeset/cold-teachers-turn.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: correct start of `{:else if}` and `{:else}` diff --git a/packages/svelte/src/compiler/legacy.js b/packages/svelte/src/compiler/legacy.js index caa7f8238e..da0ba058d3 100644 --- a/packages/svelte/src/compiler/legacy.js +++ b/packages/svelte/src/compiler/legacy.js @@ -353,11 +353,12 @@ export function convert(source, ast) { }; } + const start = node.elseif ? node.consequent.nodes[0].start : node.start; remove_surrounding_whitespace_nodes(node.consequent.nodes); return { type: 'IfBlock', - start: node.start, + start, end: node.end, expression: node.test, children: node.consequent.nodes.map( diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index baa86783b0..14af03f6f6 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -345,7 +345,7 @@ function next(parser) { /** @type {ReturnType>} */ const child = parser.append({ - start: parser.index, + start: start - 1, end: -1, type: 'IfBlock', elseif: true, diff --git a/packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte b/packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte new file mode 100644 index 0000000000..28b41c046c --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte @@ -0,0 +1,5 @@ +{#if foo} +

foo

+{:else} +

not foo

+{/if} diff --git a/packages/svelte/tests/parser-modern/samples/if-block-else/output.json b/packages/svelte/tests/parser-modern/samples/if-block-else/output.json new file mode 100644 index 0000000000..1193af156e --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-else/output.json @@ -0,0 +1,116 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 51, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "IfBlock", + "elseif": false, + "start": 0, + "end": 51, + "test": { + "type": "Identifier", + "start": 5, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "name": "foo" + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 9, + "end": 11, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 11, + "end": 21, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 14, + "end": 17, + "raw": "foo", + "data": "foo" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 21, + "end": 22, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + }, + "alternate": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 29, + "end": 31, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 31, + "end": 45, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 34, + "end": 41, + "raw": "not foo", + "data": "not foo" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 45, + "end": 46, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + } + } + ], + "transparent": false + }, + "options": null +} diff --git a/packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte b/packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte new file mode 100644 index 0000000000..2566aef258 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte @@ -0,0 +1,5 @@ +{#if x > 10} +

x is greater than 10

+{:else if x < 5} +

x is less than 5

+{/if} diff --git a/packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json b/packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json new file mode 100644 index 0000000000..e68b154a55 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json @@ -0,0 +1,211 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 89, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "IfBlock", + "elseif": false, + "start": 0, + "end": 89, + "test": { + "type": "BinaryExpression", + "start": 5, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "name": "x" + }, + "operator": ">", + "right": { + "type": "Literal", + "start": 9, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "value": 10, + "raw": "10" + } + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 12, + "end": 14, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 14, + "end": 41, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 17, + "end": 37, + "raw": "x is greater than 10", + "data": "x is greater than 10" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 41, + "end": 42, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + }, + "alternate": { + "type": "Fragment", + "nodes": [ + { + "start": 42, + "end": 89, + "type": "IfBlock", + "elseif": true, + "test": { + "type": "BinaryExpression", + "start": 52, + "end": 57, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "left": { + "type": "Identifier", + "start": 52, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "name": "x" + }, + "operator": "<", + "right": { + "type": "Literal", + "start": 56, + "end": 57, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "value": 5, + "raw": "5" + } + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 58, + "end": 60, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 60, + "end": 83, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 63, + "end": 79, + "raw": "x is less than 5", + "data": "x is less than 5" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 83, + "end": 84, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + }, + "alternate": null + } + ], + "transparent": false + } + } + ], + "transparent": false + }, + "options": null +} diff --git a/packages/svelte/tests/parser-modern/samples/if-block/input.svelte b/packages/svelte/tests/parser-modern/samples/if-block/input.svelte new file mode 100644 index 0000000000..5851347a88 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block/input.svelte @@ -0,0 +1 @@ +{#if foo}bar{/if} diff --git a/packages/svelte/tests/parser-modern/samples/if-block/output.json b/packages/svelte/tests/parser-modern/samples/if-block/output.json new file mode 100644 index 0000000000..965f2b5614 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block/output.json @@ -0,0 +1,50 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 17, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "IfBlock", + "elseif": false, + "start": 0, + "end": 17, + "test": { + "type": "Identifier", + "start": 5, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "name": "foo" + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 9, + "end": 12, + "raw": "bar", + "data": "bar" + } + ], + "transparent": false + }, + "alternate": null + } + ], + "transparent": false + }, + "options": null +}