From 64cb7abed85566ec5d0eaee13e9d4fc58198f001 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 5 Oct 2020 05:49:52 +0800 Subject: [PATCH] JS: Fix comments inside template (#9278) Co-authored-by: Georgii Dolzhykov --- changelog_unreleased/javascript/pr-9278.md | 61 ++++++++ src/language-js/embed.js | 51 ++++--- .../__snapshots__/jsfmt.spec.js.snap | 140 ++++++++++++++++++ .../js/multiparser-comments/comment-inside.js | 61 ++++++++ 4 files changed, 291 insertions(+), 22 deletions(-) create mode 100644 changelog_unreleased/javascript/pr-9278.md create mode 100644 tests/js/multiparser-comments/comment-inside.js diff --git a/changelog_unreleased/javascript/pr-9278.md b/changelog_unreleased/javascript/pr-9278.md new file mode 100644 index 000000000..0efc1a6be --- /dev/null +++ b/changelog_unreleased/javascript/pr-9278.md @@ -0,0 +1,61 @@ +#### Fix comments inside template (#9278 by @fisker) + + +```js +// Input +html`${ + foo + /* comment */ +}`; +html` +${ + foo + /* comment */ +} +`; +graphql`${ + foo + /* comment */ +}`; +css`${ + foo + /* comment */ +}`; + +// Prettier stable +html`${foo}`; +/* comment */ +html` + ${foo} + /* comment */ +`; +graphql` + ${foo} + /* comment */ +`; +css` + ${foo} + /* comment */ +`; + + +// Prettier master +html`${ + foo + /* comment */ +}`; +html` +${ + foo + /* comment */ +} +`; +graphql`${ + foo + /* comment */ +}`; +css`${ + foo + /* comment */ +}`; +``` diff --git a/src/language-js/embed.js b/src/language-js/embed.js index 1bf4ce926..371642fb5 100644 --- a/src/language-js/embed.js +++ b/src/language-js/embed.js @@ -11,6 +11,7 @@ const { concat, group, dedentToRoot, + lineSuffixBoundary, }, utils: { mapDoc, replaceNewlinesWithLiterallines }, } = require("../document"); @@ -48,7 +49,11 @@ function embed(path, print, textToDoc, options) { { parser: "scss" }, { stripTrailingHardline: true } ); - return transformCssDoc(doc, path, print); + return transformCssDoc( + doc, + node, + path.map(printTemplateExpression, "expressions") + ); } /* @@ -61,9 +66,7 @@ function embed(path, print, textToDoc, options) { * support Relay Classic formatting. */ if (isGraphQL(path)) { - const expressionDocs = node.expressions - ? path.map(print, "expressions") - : []; + const expressionDocs = path.map(printTemplateExpression, "expressions"); const numQuasis = node.quasis.length; @@ -131,7 +134,7 @@ function embed(path, print, textToDoc, options) { } if (expressionDoc) { - parts.push(concat(["${", expressionDoc, "}"])); + parts.push(expressionDoc); } } @@ -151,8 +154,8 @@ function embed(path, print, textToDoc, options) { if (htmlParser) { return printHtmlTemplateLiteral( - path, - print, + node, + path.map(printTemplateExpression, "expressions"), textToDoc, htmlParser, options @@ -207,6 +210,15 @@ function embed(path, print, textToDoc, options) { ); return escapeTemplateCharacters(doc, true); } + + function printTemplateExpression(path) { + const node = path.getValue(); + let printed = print(path); + if (node.comments && node.comments.length) { + printed = group(concat([indent(concat([softline, printed])), softline])); + } + return concat(["${", printed, lineSuffixBoundary, "}"]); + } } function getIndentation(str) { @@ -236,18 +248,13 @@ function escapeTemplateCharacters(doc, raw) { }); } -function transformCssDoc(quasisDoc, path, print) { - const parentNode = path.getValue(); - +function transformCssDoc(quasisDoc, parentNode, expressionDocs) { const isEmpty = parentNode.quasis.length === 1 && !parentNode.quasis[0].value.raw.trim(); if (isEmpty) { return "``"; } - const expressionDocs = parentNode.expressions - ? path.map(print, "expressions") - : []; const newDoc = replacePlaceholders(quasisDoc, expressionDocs); /* istanbul ignore if */ if (!newDoc) { @@ -306,7 +313,7 @@ function replacePlaceholders(quasisDoc, expressionDocs) { } // The component will always be a number at odd index - replacedParts.push("${", expressionDocs[component], "}"); + replacedParts.push(expressionDocs[component]); replaceCounter++; }); }); @@ -554,9 +561,13 @@ function isHtml(path) { // The counter is needed to distinguish nested embeds. let htmlTemplateLiteralCounter = 0; -function printHtmlTemplateLiteral(path, print, textToDoc, parser, options) { - const node = path.getValue(); - +function printHtmlTemplateLiteral( + node, + expressionDocs, + textToDoc, + parser, + options +) { const counter = htmlTemplateLiteralCounter; htmlTemplateLiteralCounter = (htmlTemplateLiteralCounter + 1) >>> 0; @@ -571,8 +582,6 @@ function printHtmlTemplateLiteral(path, print, textToDoc, parser, options) { ) .join(""); - const expressionDocs = path.map(print, "expressions"); - if (expressionDocs.length === 0 && text.trim().length === 0) { return "``"; } @@ -614,9 +623,7 @@ function printHtmlTemplateLiteral(path, print, textToDoc, parser, options) { } const placeholderIndex = +component; - parts.push( - concat(["${", group(expressionDocs[placeholderIndex]), "}"]) - ); + parts.push(expressionDocs[placeholderIndex]); } return concat(parts); diff --git a/tests/js/multiparser-comments/__snapshots__/jsfmt.spec.js.snap b/tests/js/multiparser-comments/__snapshots__/jsfmt.spec.js.snap index ce15ad5f4..f993855ec 100644 --- a/tests/js/multiparser-comments/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/multiparser-comments/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,145 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`comment-inside.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +// #9274 +html\` +
+ \${this.set && this.set.artist + /* avoid console errors if \`this.set\` is undefined */} +
+\`; + +html\`\${ + foo + /* comment */ +}\`; +html\` +\${ + foo + /* comment */ +} +\`; + + +graphql\`\${ + foo + /* comment */ +}\`; +graphql\` +\${ + foo + /* comment */ +} +\`; + + +css\`\${ + foo + /* comment */ +}\`; +css\` +\${ + foo + /* comment */ +} +\`; + +markdown\`\${ + foo + /* comment */ +}\`; +markdown\` +\${ + foo + /* comment */ +} +\`; + +// https://github.com/prettier/prettier/pull/9278#issuecomment-700589195 +expr1 = html\` +
+ \${x(foo, // fg + bar + )}
+\`; + +=====================================output===================================== +// #9274 +html\` +
+ \${ + this.set && this.set.artist + /* avoid console errors if \`this.set\` is undefined */ + } +
+\`; + +html\`\${ + foo + /* comment */ +}\`; +html\` + \${ + foo + /* comment */ + } +\`; + +graphql\` + \${ + foo + /* comment */ + } +\`; +graphql\` + \${ + foo + /* comment */ + } +\`; + +css\` + \${ + foo + /* comment */ + } +\`; +css\` + \${ + foo + /* comment */ + } +\`; + +markdown\`\${ + foo + /* comment */ +}\`; +markdown\` +\${ + foo + /* comment */ +} +\`; + +// https://github.com/prettier/prettier/pull/9278#issuecomment-700589195 +expr1 = html\` +
+ \${x( + foo, // fg + bar + )} +
+\`; + +================================================================================ +`; + exports[`comments.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow"] diff --git a/tests/js/multiparser-comments/comment-inside.js b/tests/js/multiparser-comments/comment-inside.js new file mode 100644 index 000000000..ec9191fef --- /dev/null +++ b/tests/js/multiparser-comments/comment-inside.js @@ -0,0 +1,61 @@ +// #9274 +html` +
+ ${this.set && this.set.artist + /* avoid console errors if `this.set` is undefined */} +
+`; + +html`${ + foo + /* comment */ +}`; +html` +${ + foo + /* comment */ +} +`; + + +graphql`${ + foo + /* comment */ +}`; +graphql` +${ + foo + /* comment */ +} +`; + + +css`${ + foo + /* comment */ +}`; +css` +${ + foo + /* comment */ +} +`; + +markdown`${ + foo + /* comment */ +}`; +markdown` +${ + foo + /* comment */ +} +`; + +// https://github.com/prettier/prettier/pull/9278#issuecomment-700589195 +expr1 = html` +
+ ${x(foo, // fg + bar + )}
+`;