Repository: prettier/prettier (JavaScript)

Issue:
SCSS: Prettier mangles parentheses in string mixin argument
**Prettier 2.6.2**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEABAllMAbArgEzgAIAzCCACgHIBBIigIQEoqmQAaECABxnWgDOyUAEMATmIgB3AAriEQlCOxSRATyGcARmJFgA1nBgBlEQFs4AGUxxkJZQLjbdBo8e57MAc2QwxuJxA4My04fEJ8SxEoL1wRLzgAMQgxMxEYPhjkEBFcGAgOEAALGDNsAHUi9HgBDzA4YwVq9AA3arVssAFNEExHMRgZXS80uwdAgCsBAA9jb2w4AEVcCHgx7EdODzF+7IEunu4xTBhy9HwYIuQADgAGLclHct1ubKO4fpbbTgBHFfghjxFDkBABaKBwMJhQpiOB-dCwobxUZIewbQKOMzoXz+DHzJb-Wyo8acGAiLRnC5XJAAJlJunQ2G8AGEIGYUUEBABWQq4RwAFXJijRmxALQCAEkoIRYMYwMdeDRpcYYGoFutHABfTVAA)
<!-- prettier-ignore -->
```sh
--parser scss
```

**Input:**
<!-- prettier-ignore -->
```scss
@include foo('A (B)')
```

**Output:**
<!-- prettier-ignore -->
```scss
@include foo("A( B)");

```

**Expected behavior:** Prettier should never modify the contents of a string.



Discussion:
Prettier outputs in single quates if the `--single-quote` option is set.
https://prettier.io/docs/en/options.html#quotes

Is this option not enough?
The issue is the parentheses, not the quotes.
Oh, sorry. I misunderstood.
I have noticed that the parentheses are in different positions.
`A (B)` -> `A( B)`
I have investigated again.
In `src/language-css/parser-postcss.js`, the spaces after `(` are moved. This processing seems to mangle parentheses.

https://github.com/prettier/prettier/blob/62195dd1f2c6b076789f0ea0ac7056e03744a22a/src/language-css/parser-postcss.js#L557-L560
One year we haven't fixed it?
After validation, we had this bug at least in v1.13, may in 1.0.



Patch:
diff --git a/changelog_unreleased/scss/17836.md b/changelog_unreleased/scss/17836.md
new file mode 100644
index 000000000000..3e101f5812bb
--- /dev/null
+++ b/changelog_unreleased/scss/17836.md
@@ -0,0 +1,19 @@
+#### Fix parentheses space problem in mixin argument (#17836 by @kovsu)
+
+<!-- prettier-ignore -->
+```scss
+// Input
+.foo {
+  @include bar('A (B)');
+}
+
+// Prettier stable
+.foo {
+  @include bar('A( B)');
+}
+
+// Prettier main
+.foo {
+  @include bar('A (B)');
+}
+```
diff --git a/src/language-css/parser-postcss.js b/src/language-css/parser-postcss.js
index c7923a53238a..b4dce497104e 100644
--- a/src/language-css/parser-postcss.js
+++ b/src/language-css/parser-postcss.js
@@ -337,7 +337,7 @@ function parseNestedCSS(node, options) {
         params = params.replace(/(\$\S+?)(\s+)?\.{3}/u, "$1...$2");
         // Remove unnecessary spaces before SCSS control, mixin and function directives
         // Move spaces after the `(`, so we can keep the range correct
-        params = params.replace(/^(?!if)(\S+)(\s+)\(/u, "$1($2");
+        params = params.replace(/^(?!if)([^"'\s]+)(\s+)\(/u, "$1($2");
 
         node.value = parseValue(params, options);
         delete node.params;


Test patch:
diff --git a/tests/format/scss/include/__snapshots__/format.test.js.snap b/tests/format/scss/include/__snapshots__/format.test.js.snap
new file mode 100644
index 000000000000..7272e12288be
--- /dev/null
+++ b/tests/format/scss/include/__snapshots__/format.test.js.snap
@@ -0,0 +1,23 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`include.scss format 1`] = `
+====================================options=====================================
+parsers: ["scss"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+h1 {
+  @include foo   ('A');
+  @include bar('A (B)');
+  @include baz   ('A (B)');
+}
+
+=====================================output=====================================
+h1 {
+  @include foo("A");
+  @include bar("A (B)");
+  @include baz("A (B)");
+}
+
+================================================================================
+`;
diff --git a/tests/format/scss/include/format.test.js b/tests/format/scss/include/format.test.js
new file mode 100644
index 000000000000..88aa93e6a77c
--- /dev/null
+++ b/tests/format/scss/include/format.test.js
@@ -0,0 +1,1 @@
+runFormatTest(import.meta, ["scss"]);
diff --git a/tests/format/scss/include/include.scss b/tests/format/scss/include/include.scss
new file mode 100644
index 000000000000..2db96e3b2185
--- /dev/null
+++ b/tests/format/scss/include/include.scss
@@ -0,0 +1,5 @@
+h1 {
+  @include foo   ('A');
+  @include bar('A (B)');
+  @include baz   ('A (B)');
+}