fix: allow leading and trailing comments in mustache tag (#11866)

Fixes #7456

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/12450/head
BlueGreenMagick 4 months ago committed by GitHub
parent a8dc96eb43
commit 81ed425b5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: allow leading and trailing comments in mustache expression

@ -129,6 +129,11 @@ function transform(name, dest) {
} }
}); });
if (comments.length > 0) {
// @ts-expect-error
(ast.trailingComments ||= []).push(...comments);
}
const category = messages[name]; const category = messages[name];
// find the `export function CODE` node // find the `export function CODE` node

@ -30,6 +30,7 @@ export function parse(source, typescript) {
* @param {string} source * @param {string} source
* @param {boolean} typescript * @param {boolean} typescript
* @param {number} index * @param {number} index
* @returns {acorn.Expression & { leadingComments?: CommentWithLocation[]; trailingComments?: CommentWithLocation[]; }}
*/ */
export function parse_expression_at(source, typescript, index) { export function parse_expression_at(source, typescript, index) {
const parser = typescript ? ParserWithTS : acorn.Parser; const parser = typescript ? ParserWithTS : acorn.Parser;
@ -92,7 +93,7 @@ function get_comment_handlers(source) {
if (comments.length === 0) return; if (comments.length === 0) return;
walk(ast, null, { walk(ast, null, {
_(node, { next }) { _(node, { next, path }) {
let comment; let comment;
while (comments[0] && comments[0].start < node.start) { while (comments[0] && comments[0].start < node.start) {
@ -103,14 +104,20 @@ function get_comment_handlers(source) {
next(); next();
if (comments[0]) { if (comments[0]) {
const slice = source.slice(node.end, comments[0].start); const parent = path.at(-1);
if (parent === undefined || node.end !== parent.end) {
const slice = source.slice(node.end, comments[0].start);
if (/^[,) \t]*$/.test(slice)) { if (/^[,) \t]*$/.test(slice)) {
node.trailingComments = [/** @type {CommentWithLocation} */ (comments.shift())]; node.trailingComments = [/** @type {CommentWithLocation} */ (comments.shift())];
}
} }
} }
} }
}); });
if (comments.length > 0) {
(ast.trailingComments ||= []).push(...comments.splice(0));
}
} }
}; };
} }

@ -17,6 +17,10 @@ export default function read_expression(parser) {
} }
let index = /** @type {number} */ (node.end); let index = /** @type {number} */ (node.end);
if (node.trailingComments !== undefined && node.trailingComments.length > 0) {
index = node.trailingComments.at(-1).end;
}
while (num_parens > 0) { while (num_parens > 0) {
const char = parser.template[index]; const char = parser.template[index];

@ -15,9 +15,14 @@ export default function tag(parser) {
parser.allow_whitespace(); parser.allow_whitespace();
if (parser.eat('#')) return open(parser); if (parser.eat('#')) return open(parser);
if (parser.eat('/')) return close(parser);
if (parser.eat(':')) return next(parser); if (parser.eat(':')) return next(parser);
if (parser.eat('@')) return special(parser); if (parser.eat('@')) return special(parser);
if (parser.match('/')) {
if (!parser.match('/*') && !parser.match('//')) {
parser.eat('/');
return close(parser);
}
}
const expression = read_expression(parser); const expression = read_expression(parser);

@ -1,6 +1,7 @@
<script> <script>
// a leading comment // a leading comment
const a = true; // a trailing comment const a = 1; // a trailing comment
const b = 2;
/** a comment */ /** a comment */
function asd() { function asd() {
@ -14,4 +15,10 @@
/* another comment */ /* another comment */
fn(); fn();
}} }}
></button> >
{/* leading block comment */ a}
</button>
{ // leading line comment
a + b // trailing line comment
/* trailing block comment */
}

@ -1,39 +1,39 @@
{ {
"html": { "html": {
"type": "Fragment", "type": "Fragment",
"start": 122, "start": 133,
"end": 207, "end": 341,
"children": [ "children": [
{ {
"type": "Text", "type": "Text",
"start": 120, "start": 131,
"end": 122, "end": 133,
"raw": "\n\n", "raw": "\n\n",
"data": "\n\n" "data": "\n\n"
}, },
{ {
"type": "Element", "type": "Element",
"start": 122, "start": 133,
"end": 207, "end": 251,
"name": "button", "name": "button",
"attributes": [ "attributes": [
{ {
"start": 131, "start": 142,
"end": 196, "end": 207,
"type": "EventHandler", "type": "EventHandler",
"name": "click", "name": "click",
"modifiers": [], "modifiers": [],
"expression": { "expression": {
"type": "ArrowFunctionExpression", "type": "ArrowFunctionExpression",
"start": 153, "start": 164,
"end": 195, "end": 206,
"loc": { "loc": {
"start": { "start": {
"line": 13, "line": 14,
"column": 1 "column": 1
}, },
"end": { "end": {
"line": 16, "line": 17,
"column": 2 "column": 2
} }
}, },
@ -44,58 +44,58 @@
"params": [], "params": [],
"body": { "body": {
"type": "BlockStatement", "type": "BlockStatement",
"start": 159, "start": 170,
"end": 195, "end": 206,
"loc": { "loc": {
"start": { "start": {
"line": 13, "line": 14,
"column": 7 "column": 7
}, },
"end": { "end": {
"line": 16, "line": 17,
"column": 2 "column": 2
} }
}, },
"body": [ "body": [
{ {
"type": "ExpressionStatement", "type": "ExpressionStatement",
"start": 187, "start": 198,
"end": 192, "end": 203,
"loc": { "loc": {
"start": { "start": {
"line": 15, "line": 16,
"column": 2 "column": 2
}, },
"end": { "end": {
"line": 15, "line": 16,
"column": 7 "column": 7
} }
}, },
"expression": { "expression": {
"type": "CallExpression", "type": "CallExpression",
"start": 187, "start": 198,
"end": 191, "end": 202,
"loc": { "loc": {
"start": { "start": {
"line": 15, "line": 16,
"column": 2 "column": 2
}, },
"end": { "end": {
"line": 15, "line": 16,
"column": 6 "column": 6
} }
}, },
"callee": { "callee": {
"type": "Identifier", "type": "Identifier",
"start": 187, "start": 198,
"end": 189, "end": 200,
"loc": { "loc": {
"start": { "start": {
"line": 15, "line": 16,
"column": 2 "column": 2
}, },
"end": { "end": {
"line": 15, "line": 16,
"column": 4 "column": 4
} }
}, },
@ -108,8 +108,8 @@
{ {
"type": "Block", "type": "Block",
"value": " another comment ", "value": " another comment ",
"start": 163, "start": 174,
"end": 184 "end": 195
} }
] ]
} }
@ -119,33 +119,159 @@
{ {
"type": "Line", "type": "Line",
"value": " comment", "value": " comment",
"start": 141, "start": 152,
"end": 151 "end": 162
} }
] ]
} }
} }
], ],
"children": [] "children": [
{
"type": "Text",
"start": 209,
"end": 210,
"raw": "\n",
"data": "\n"
},
{
"type": "MustacheTag",
"start": 210,
"end": 241,
"expression": {
"type": "Identifier",
"start": 239,
"end": 240,
"loc": {
"start": {
"line": 19,
"column": 29
},
"end": {
"line": 19,
"column": 30
}
},
"name": "a",
"leadingComments": [
{
"type": "Block",
"value": " leading block comment ",
"start": 211,
"end": 238
}
]
}
},
{
"type": "Text",
"start": 241,
"end": 242,
"raw": "\n",
"data": "\n"
}
]
},
{
"type": "Text",
"start": 251,
"end": 252,
"raw": "\n",
"data": "\n"
},
{
"type": "MustacheTag",
"start": 252,
"end": 341,
"expression": {
"type": "BinaryExpression",
"start": 279,
"end": 284,
"loc": {
"start": {
"line": 22,
"column": 1
},
"end": {
"line": 22,
"column": 6
}
},
"left": {
"type": "Identifier",
"start": 279,
"end": 280,
"loc": {
"start": {
"line": 22,
"column": 1
},
"end": {
"line": 22,
"column": 2
}
},
"name": "a"
},
"operator": "+",
"right": {
"type": "Identifier",
"start": 283,
"end": 284,
"loc": {
"start": {
"line": 22,
"column": 5
},
"end": {
"line": 22,
"column": 6
}
},
"name": "b"
},
"leadingComments": [
{
"type": "Line",
"value": " leading line comment",
"start": 254,
"end": 277
}
],
"trailingComments": [
{
"type": "Line",
"value": " trailing line comment",
"start": 285,
"end": 309
},
{
"type": "Block",
"value": " trailing block comment ",
"start": 311,
"end": 339
}
]
}
} }
] ]
}, },
"instance": { "instance": {
"type": "Script", "type": "Script",
"start": 0, "start": 0,
"end": 120, "end": 131,
"context": "default", "context": "default",
"content": { "content": {
"type": "Program", "type": "Program",
"start": 8, "start": 8,
"end": 111, "end": 122,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": { "end": {
"line": 9, "line": 10,
"column": 0 "column": 0
} }
}, },
@ -153,7 +279,7 @@
{ {
"type": "VariableDeclaration", "type": "VariableDeclaration",
"start": 32, "start": 32,
"end": 47, "end": 44,
"loc": { "loc": {
"start": { "start": {
"line": 3, "line": 3,
@ -161,14 +287,14 @@
}, },
"end": { "end": {
"line": 3, "line": 3,
"column": 16 "column": 13
} }
}, },
"declarations": [ "declarations": [
{ {
"type": "VariableDeclarator", "type": "VariableDeclarator",
"start": 38, "start": 38,
"end": 46, "end": 43,
"loc": { "loc": {
"start": { "start": {
"line": 3, "line": 3,
@ -176,7 +302,7 @@
}, },
"end": { "end": {
"line": 3, "line": 3,
"column": 15 "column": 12
} }
}, },
"id": { "id": {
@ -198,7 +324,7 @@
"init": { "init": {
"type": "Literal", "type": "Literal",
"start": 42, "start": 42,
"end": 46, "end": 43,
"loc": { "loc": {
"start": { "start": {
"line": 3, "line": 3,
@ -206,11 +332,11 @@
}, },
"end": { "end": {
"line": 3, "line": 3,
"column": 15 "column": 12
} }
}, },
"value": true, "value": 1,
"raw": "true" "raw": "1"
} }
} }
], ],
@ -227,36 +353,102 @@
{ {
"type": "Line", "type": "Line",
"value": " a trailing comment", "value": " a trailing comment",
"start": 48, "start": 45,
"end": 69 "end": 66
} }
] ]
}, },
{
"type": "VariableDeclaration",
"start": 68,
"end": 80,
"loc": {
"start": {
"line": 4,
"column": 1
},
"end": {
"line": 4,
"column": 13
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 74,
"end": 79,
"loc": {
"start": {
"line": 4,
"column": 7
},
"end": {
"line": 4,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 74,
"end": 75,
"loc": {
"start": {
"line": 4,
"column": 7
},
"end": {
"line": 4,
"column": 8
}
},
"name": "b"
},
"init": {
"type": "Literal",
"start": 78,
"end": 79,
"loc": {
"start": {
"line": 4,
"column": 11
},
"end": {
"line": 4,
"column": 12
}
},
"value": 2,
"raw": "2"
}
}
],
"kind": "const"
},
{ {
"type": "FunctionDeclaration", "type": "FunctionDeclaration",
"start": 90, "start": 101,
"end": 110, "end": 121,
"loc": { "loc": {
"start": { "start": {
"line": 6, "line": 7,
"column": 1 "column": 1
}, },
"end": { "end": {
"line": 8, "line": 9,
"column": 2 "column": 2
} }
}, },
"id": { "id": {
"type": "Identifier", "type": "Identifier",
"start": 99, "start": 110,
"end": 102, "end": 113,
"loc": { "loc": {
"start": { "start": {
"line": 6, "line": 7,
"column": 10 "column": 10
}, },
"end": { "end": {
"line": 6, "line": 7,
"column": 13 "column": 13
} }
}, },
@ -268,15 +460,15 @@
"params": [], "params": [],
"body": { "body": {
"type": "BlockStatement", "type": "BlockStatement",
"start": 105, "start": 116,
"end": 110, "end": 121,
"loc": { "loc": {
"start": { "start": {
"line": 6, "line": 7,
"column": 16 "column": 16
}, },
"end": { "end": {
"line": 8, "line": 9,
"column": 2 "column": 2
} }
}, },
@ -286,8 +478,8 @@
{ {
"type": "Block", "type": "Block",
"value": "* a comment ", "value": "* a comment ",
"start": 72, "start": 83,
"end": 88 "end": 99
} }
] ]
} }

Loading…
Cancel
Save