Repository: sveltejs/prettier-plugin-svelte (ts)

Issue:
Comments are removed from inline event listeners
For instance
```jsx
<svelte:body on:keydown={(e) => {
	// hello world
}} />
// -- PRETTIER ->
<svelte:body on:keydown={(e) => {}} />
```

Pull request description:
Handle comments in event handlers
Fixes #96: preserve comments in event handlers.


Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..2e3e594
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,15 @@
+name: CI
+on: pull_request
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions/setup-node@v1
+
+      - name: Install packages
+        run: npm install
+      - name: Run tests
+        run: npm test
diff --git a/src/embed.ts b/src/embed.ts
index fa1b700..6b0b00a 100644
--- a/src/embed.ts
+++ b/src/embed.ts
@@ -11,7 +11,7 @@ import {
 import { Node } from './print/nodes';
 
 const {
-    builders: { concat, hardline, group, indent, align, literalline },
+    builders: { concat, hardline, group, indent, literalline },
     utils: { removeLines },
 } = doc;
 
@@ -25,7 +25,7 @@ export function embed(
 
     if (node.isJS) {
         return removeLines(
-            textToDoc(getText(node, options), {
+            textToDoc(forceIntoExpression(getText(node, options)), {
                 parser: expressionParser,
                 singleQuote: true,
             }),
@@ -61,12 +61,16 @@ export function embed(
     return null;
 }
 
+function forceIntoExpression(statement: string) {
+    // note the trailing newline: if the statement ends in a // comment, 
+    // we can't add the closing bracket right afterwards
+    return `(${statement}\n)`;
+}
+
 function expressionParser(text: string, parsers: any) {
-    const ast = parsers.babel(`(${text})`);
-    return {
-        type: 'File',
-        program: ast.program.body[0].expression,
-    };
+    const ast = parsers.babel(text);
+
+    return { ...ast, program: ast.program.body[0].expression };
 }
 
 function skipBlank(docs: Doc[]): number {
@@ -110,14 +114,10 @@ function nukeLastLine(doc: Doc): Doc {
 function preformattedBody(str: string): Doc {
     const firstNewline = /^[\t\f\r ]*\n/;
     const lastNewline = /\n[\t\f\r ]*$/;
-    
+
     // If we do not start with a new line prettier might try to break the opening tag
     // to keep it together with the string. Use a literal line to skip indentation.
-    return concat([
-        literalline,
-        str.replace(firstNewline, '').replace(lastNewline, ''),
-        hardline,
-    ]);
+    return concat([literalline, str.replace(firstNewline, '').replace(lastNewline, ''), hardline]);
 }
 
 function getSnippedContent(node: Node) {
diff --git a/src/lib/getText.ts b/src/lib/getText.ts
index 87234fb..3700076 100644
--- a/src/lib/getText.ts
+++ b/src/lib/getText.ts
@@ -2,5 +2,14 @@ import { ParserOptions } from 'prettier';
 import { Node } from '../print/nodes';
 
 export function getText(node: Node, options: ParserOptions) {
-    return options.originalText.slice(options.locStart(node), options.locEnd(node));
+    const leadingComments: Node[] = (node as any).leadingComments
+
+    return options.originalText.slice(
+        options.locStart(
+            // if there are comments before the node they are not included 
+            // in the `start` of the node itself
+            leadingComments && leadingComments[0] || node,
+        ),
+        options.locEnd(node),
+    );
 }


Test patch:
diff --git a/test/printer/samples/event-handler-comments.html b/test/printer/samples/event-handler-comments.html
new file mode 100644
index 0000000..2475fbc
--- /dev/null
+++ b/test/printer/samples/event-handler-comments.html
@@ -0,0 +1,6 @@
+<button
+    on:click={// comment
+    () => {
+        /* another comment */
+        fn();
+    }} />