Repository: prettier/prettier (JavaScript)

Issue:
Emotion css broken by space added between templated function name and opening parenthesis
**Prettier 2.4.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuc0DOMAEAHAhgJ1wHNDsALTAXkzDTQAMAdKTTAM2hgFo0BLALzhJMARgBM2AB4BuZs1YxCUNB3wBbYQBJgANzj4sAfkwByRbmUAbXPACaJzMLNK01+AA0TAXwAU281Y2vNCYANSYZBYAJpZwAPJsbGhwMF5SAJSyUPRZIAA0IBDYMMHKyKAE+BAA7gAKBAhoyCC4ltW4AJ5NBQBGhGAA1ikAyrhqcAAyvFBwyGytyb39QzDDeGDTRMiKAK5wBXBqPXBRUScTFkQ7xHAAYhDqNiVQWyi4OzAQ+SBkMGqWAHUyLx4Gh1nBho0QbwdCCOs1aN0QNNkgZaoQiGpcHMFvsQAArNCSYabWIARR2EHgOMsixAeHwqOaPVwx0s32w+GmMABvCiMDIyHEAAYCpyIMkAaRmpy4Ki9N8AI6U+DoopNN5oLgzE4nb74ODK3gG9HELE0unJNS8bb4PYFPgvckq2ZIea0vEwVm8-mCpBiArmXiWTYAYQganNKDlAFZvjtkgAVVka910nR7ACSUDOsGGYC5xQAgjnhjAOrELXAvF4gA)
<!-- prettier-ignore -->
```sh
--parser babel
--print-width 120
```

**Input:**
<!-- prettier-ignore -->
```jsx
const paragraph = css`
  font-size: 12px;

  transform: ${vert ? 'translateY' : 'translateX'}(${translation + handleOffset}px);
`;

```

**Output:**
<!-- prettier-ignore -->
```jsx
const paragraph = css`
  font-size: 12px;

  transform: ${vert ? "translateY" : "translateX"} (${translation + handleOffset}px);
`;

```

**Expected behavior:**
Do not add a space between the css function name and the opening parenthesis.


Hints:

Patch:
diff --git a/src/language-css/printer-postcss.js b/src/language-css/printer-postcss.js
--- a/src/language-css/printer-postcss.js
+++ b/src/language-css/printer-postcss.js
@@ -75,6 +75,7 @@ const {
   lastLineHasInlineComment,
   isAtWordPlaceholderNode,
   isConfigurationNode,
+  isParenGroupNode,
 } = require("./utils.js");
 const { locStart, locEnd } = require("./loc.js");
 
@@ -810,14 +811,15 @@ function genericPrint(path, options, print) {
         }
 
         if (
-          iNode.value === "with" &&
-          iNextNode &&
-          iNextNode.type === "value-paren_group" &&
-          iNextNode.open &&
-          iNextNode.open.value === "(" &&
-          iNextNode.close &&
-          iNextNode.close.value === ")"
+          isAtWordPlaceholderNode(iNode) &&
+          isParenGroupNode(iNextNode) &&
+          locEnd(iNode) === locStart(iNextNode.open)
         ) {
+          parts.push(softline);
+          continue;
+        }
+
+        if (iNode.value === "with" && isParenGroupNode(iNextNode)) {
           parts.push(" ");
           continue;
         }
diff --git a/src/language-css/utils.js b/src/language-css/utils.js
--- a/src/language-css/utils.js
+++ b/src/language-css/utils.js
@@ -508,6 +508,16 @@ function isConfigurationNode(node, parentNode) {
   return false;
 }
 
+function isParenGroupNode(node) {
+  return (
+    node.type === "value-paren_group" &&
+    node.open &&
+    node.open.value === "(" &&
+    node.close &&
+    node.close.value === ")"
+  );
+}
+
 module.exports = {
   getAncestorCounter,
   getAncestorNode,
@@ -564,4 +574,5 @@ module.exports = {
   isAtWordPlaceholderNode,
   isModuleRuleName,
   isConfigurationNode,
+  isParenGroupNode,
 };


Test patch:
diff --git a/tests/format/js/multiparser-css/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/multiparser-css/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/js/multiparser-css/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/js/multiparser-css/__snapshots__/jsfmt.spec.js.snap
@@ -401,6 +401,43 @@ const style3 = css\`
 ================================================================================
 `;
 
+exports[`issue-11797.js format 1`] = `
+====================================options=====================================
+parsers: ["babel", "typescript", "flow"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+const paragraph1 = css\`
+  font-size: 12px;
+  transform: \${vert ? 'translateY' : 'translateX'}(\${translation + handleOffset}px);
+\`;
+
+const paragraph2 = css\`
+  transform: \${expr}(30px);
+\`;
+
+const paragraph3 = css\`
+  transform: \${expr} (30px);
+\`;
+
+=====================================output=====================================
+const paragraph1 = css\`
+  font-size: 12px;
+  transform: \${vert ? "translateY" : "translateX"}
+    (\${translation + handleOffset}px);
+\`;
+
+const paragraph2 = css\`
+  transform: \${expr}(30px);
+\`;
+
+const paragraph3 = css\`
+  transform: \${expr} (30px);
+\`;
+
+================================================================================
+`;
+
 exports[`styled-components.js format 1`] = `
 ====================================options=====================================
 parsers: ["babel", "typescript", "flow"]
diff --git a/tests/format/js/multiparser-css/issue-11797.js b/tests/format/js/multiparser-css/issue-11797.js
new file mode 100644
--- /dev/null
+++ b/tests/format/js/multiparser-css/issue-11797.js
@@ -0,0 +1,12 @@
+const paragraph1 = css`
+  font-size: 12px;
+  transform: ${vert ? 'translateY' : 'translateX'}(${translation + handleOffset}px);
+`;
+
+const paragraph2 = css`
+  transform: ${expr}(30px);
+`;
+
+const paragraph3 = css`
+  transform: ${expr} (30px);
+`;