Repository: prettier/prettier (JavaScript)
Date: 2020-06-22 04:38:28+00:00
Task type: Bug Fix

Issue:
Inconsistent formatting on Vue double curly braces template variables
**Prettier 2.0.5**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEAeeBbADgGwIbwB8AOlAARmoAmAlgG5lj4DOzAvMSAE5xWcnkKZAOpwyeHmQDmEGlClkYEcVSqKAFjWZlmNbDjFgJa9XB6kKqAPS06Ay7cYt2nHnxD2hw9QTJbpsvJk0GTAwGRYXBBYAIxkAL7x4lBqYRFRWABMCfEWlDb0AtaYuARwAiAANCDRMDTQzMigElEA7gAKEgiNKHg4rXgAno3VAEZceGAA1nAwAMpYk3JSyDBcAK5w1eowGDjeNPDMi2Bwc92H9IeDyCA0UlAQPFV3UMxmMO0TUhh4yABmfXe1QAVswAB4AIQm01mczwGDgABk5HAAUCtiAweC5ssDABFdYQeDonDAkCLLjvLi3OibF6ROQwYQ0KgwdTIAAcAAZqpEIO9hBMsLdInBqXQ0dUAI5E+BfaI9EB4ZgAWigcF4vBePFlNB4XzwPz+SEBZMx7wwNFWGwteLghOJaNNGOqMDwoxZbI5SEybomNBwywAwhAML9buKAKwvdbvAAqHp6ZvJdLgAEkUgh5mAuDQsDAAIIpOYwQYGUnvRJAA)
```sh
--html-whitespace-sensitivity ignore
--parser vue
```

**Input:**
```vue
<template>
  <div class="red">
    We are going to add this simple card here
  </div>
  <div class="red">
    What is going on {{ prop1 }} and {{ prop2 }}
  </div>
</template>

```

**Output:**
```vue
<template>
  <div class="red">
    We are going to add this simple card here
  </div>
  <div class="red">What is going on {{ prop1 }} and {{ prop2 }}</div>
</template>

```

**Expected behavior:**
I expected that it makes no difference between the first and second div block in terms of formatting.  Only when I add prop values do i get the error/recommendation to keep everything on one line.  If I switch the parser to HTML it will not attempt to change or throw the error.  This is when working within .vue component files.


Issue discussion:

Solution patch:
diff --git a/changelog_unreleased/html/pr-8614.md b/changelog_unreleased/html/pr-8614.md
new file mode 100644
index 000000000000..19d77a66aee0
--- /dev/null
+++ b/changelog_unreleased/html/pr-8614.md
@@ -0,0 +1,26 @@
+#### Don't preserve line breaks around text-only content ([#8614](https://github.com/prettier/prettier/pull/8614) by [@fisker](https://github.com/fisker))
+
+Previously, Prettier always [preserved line breaks][#5596] around inline nodes (i.e. inline elements, text, interpolations). In general, Prettier, as much as possible, tries to avoid relying on original formatting, but there are at least two cases when collapsing inline nodes into a single line is undesirable, namely list-like content and conditional constructions (e.g. `v-if`/`v-else` in Vue). A good way to detect those cases couldn't be found, so such a trade-off was made. It turned out, however, for text-only content, this relaxation of rules was unnecessary and only led to confusingly inconsistent formatting.
+
+<!-- prettier-ignore -->
+```html
+<!-- Input -->
+<div>
+  Hello, world!
+</div>
+<div>
+  Hello, {{ username }}!
+</div>
+
+<!-- Prettier stable -->
+<div>
+  Hello, world!
+</div>
+<div>Hello, {{ username }}!</div>
+
+<!-- Prettier master -->
+<div>Hello, world!</div>
+<div>Hello, {{ username }}!</div>
+```
+
+[#5596]: https://prettier.io/blog/2019/01/20/1.16.0.html#respect-surrounding-linebreaks-5596-by-ikatyang
diff --git a/src/language-html/utils.js b/src/language-html/utils.js
index 70098d73a9ad..2b9a0bac6147 100644
--- a/src/language-html/utils.js
+++ b/src/language-html/utils.js
@@ -288,6 +288,7 @@ function forceBreakContent(node) {
         node.children.some((child) => hasNonTextChild(child)))) ||
     (node.firstChild &&
       node.firstChild === node.lastChild &&
+      node.firstChild.type !== "text" &&
       hasLeadingLineBreak(node.firstChild) &&
       (!node.lastChild.isTrailingSpaceSensitive ||
         hasTrailingLineBreak(node.lastChild)))


Test patch:
diff --git a/tests/angular/angular/__snapshots__/jsfmt.spec.js.snap b/tests/angular/angular/__snapshots__/jsfmt.spec.js.snap
index dac2d08b4fb5..2eb34a77df39 100644
--- a/tests/angular/angular/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/angular/angular/__snapshots__/jsfmt.spec.js.snap
@@ -4791,9 +4791,7 @@ can be found in the LICENSE file at http://angular.io/license
 <div [class.special]="isSpecial">Special</div>
 <br /><br />
 
-<button [style.color]="isSpecial ? 'red' : 'green'">
-  button
-</button>
+<button [style.color]="isSpecial ? 'red' : 'green'">button</button>
 
 <a class="to-toc" href="#toc">top</a>
 
@@ -6359,9 +6357,7 @@ can be found in the LICENSE file at http://angular.io/license
 <br />
 <br />
 
-<button [style.color]="isSpecial ? 'red' : 'green'">
-  button
-</button>
+<button [style.color]="isSpecial ? 'red' : 'green'">button</button>
 
 <a class="to-toc" href="#toc">top</a>
 
@@ -11403,9 +11399,7 @@ can be found in the LICENSE file at http://angular.io/license
 <div [class.special]="isSpecial">Special</div>
 <br /><br />
 
-<button [style.color]="isSpecial ? 'red' : 'green'">
-  button
-</button>
+<button [style.color]="isSpecial ? 'red' : 'green'">button</button>
 
 <a class="to-toc" href="#toc">top</a>
 
@@ -12931,9 +12925,7 @@ can be found in the LICENSE file at http://angular.io/license
 <div [class.special]="isSpecial">Special</div>
 <br /><br />
 
-<button [style.color]="isSpecial ? 'red' : 'green'">
-  button
-</button>
+<button [style.color]="isSpecial ? 'red' : 'green'">button</button>
 
 <a class="to-toc" href="#toc">top</a>
 
diff --git a/tests/html/front-matter/__snapshots__/jsfmt.spec.js.snap b/tests/html/front-matter/__snapshots__/jsfmt.spec.js.snap
index 99cacfb82522..b79cca5d1846 100644
--- a/tests/html/front-matter/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/html/front-matter/__snapshots__/jsfmt.spec.js.snap
@@ -24,9 +24,7 @@ slug: home
 
 ---
 
-<h1>
-  Hello world!
-</h1>
+<h1>Hello world!</h1>
 
 ================================================================================
 `;
diff --git a/tests/html/svg/__snapshots__/jsfmt.spec.js.snap b/tests/html/svg/__snapshots__/jsfmt.spec.js.snap
index ff130189649d..46c9a4ff480b 100644
--- a/tests/html/svg/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/html/svg/__snapshots__/jsfmt.spec.js.snap
@@ -99,12 +99,8 @@ printWidth: 80
       In the context of SVG embeded into HTML, the XHTML namespace could be avoided, but it is mandatory in the context of an SVG document
     -->
     <div xmlns="http://www.w3.org/1999/xhtml">
-      <p>
-        123
-      </p>
-      <span>
-        123
-      </span>
+      <p>123</p>
+      <span> 123 </span>
     </div>
   </foreignObject>
 </svg>
diff --git a/tests/html/tags/__snapshots__/jsfmt.spec.js.snap b/tests/html/tags/__snapshots__/jsfmt.spec.js.snap
index 598ef8c07d1d..9f69c5f40405 100644
--- a/tests/html/tags/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/html/tags/__snapshots__/jsfmt.spec.js.snap
@@ -1444,9 +1444,7 @@ ___________________________
              ||     ||
 ___________________________
   </pre>
-  <figcaption id="cow-caption">
-    A cow saying, "I'm an expert in my field." The cow is illustrated using preformatted text characters.
-  </figcaption>
+  <figcaption id="cow-caption">A cow saying, "I'm an expert in my field." The cow is illustrated using preformatted text characters.</figcaption>
 </figure>
 <pre data-attr-1="foo" data-attr-2="foo" data-attr-3="foo" data-attr-4="foo" data-attr-5="foo" data-attr-6="foo">
      Foo     Bar
@@ -2849,9 +2847,7 @@ printWidth: Infinity
   <app-footer [input]="something"></app-footer>
 </div>
 <x:root><span>tag name in other namespace should also lower cased</span></x:root>
-<div>
-  Lorem ipsum dolor sit amet, consectetur adipiscing elit, "<strong>seddoeiusmod</strong>".
-</div>
+<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, "<strong>seddoeiusmod</strong>".</div>
 <div>
   Lorem ipsum dolor sit amet, consectetur adipiscing elit,
   <strong>seddoeiusmod</strong>.
diff --git a/tests/html/whitespace/__snapshots__/jsfmt.spec.js.snap b/tests/html/whitespace/__snapshots__/jsfmt.spec.js.snap
index 7176eac75aff..9441233f75e1 100644
--- a/tests/html/whitespace/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/html/whitespace/__snapshots__/jsfmt.spec.js.snap
@@ -517,18 +517,12 @@ printWidth: 80
 <span>123</span>
 <span> 123</span>
 <span>123 </span>
-<span>
-  123
-</span>
+<span> 123 </span>
 
 <div>123</div>
-<div>
-  123
-</div>
 <div>123</div>
-<div>
-  123
-</div>
+<div>123</div>
+<div>123</div>
 
 ================================================================================
 `;
diff --git a/tests/mjml/mjml/__snapshots__/jsfmt.spec.js.snap b/tests/mjml/mjml/__snapshots__/jsfmt.spec.js.snap
index aabb76351f4d..297ff67b0e76 100644
--- a/tests/mjml/mjml/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/mjml/mjml/__snapshots__/jsfmt.spec.js.snap
@@ -48,9 +48,7 @@ printWidth: 80
 =====================================output=====================================
 <mjml>
   <mj-head>
-    <mj-title>
-      The green fix eats mango.
-    </mj-title>
+    <mj-title> The green fix eats mango. </mj-title>
     <mj-breakpoint width="600px" />
     <mj-preview>Do you like cheese? We do!</mj-preview>
     <mj-attributes>
diff --git a/tests/vue/interpolation/__snapshots__/jsfmt.spec.js.snap b/tests/vue/interpolation/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..3b930d98f422
--- /dev/null
+++ b/tests/vue/interpolation/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`template.vue format 1`] = `
+====================================options=====================================
+parsers: ["vue"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+<template>
+  <root>
+<div class="red">
+    We are going to add this simple card here
+  </div>
+  <div class="red">
+    What is going on {{ prop1 }} and {{ prop2 }}
+  </div>
+  </root>
+</template>
+
+=====================================output=====================================
+<template>
+  <root>
+    <div class="red">We are going to add this simple card here</div>
+    <div class="red">What is going on {{ prop1 }} and {{ prop2 }}</div>
+  </root>
+</template>
+
+================================================================================
+`;
diff --git a/tests/vue/interpolation/jsfmt.spec.js b/tests/vue/interpolation/jsfmt.spec.js
new file mode 100644
index 000000000000..2fd7eede986d
--- /dev/null
+++ b/tests/vue/interpolation/jsfmt.spec.js
@@ -0,0 +1,1 @@
+run_spec(__dirname, ["vue"]);
diff --git a/tests/vue/interpolation/template.vue b/tests/vue/interpolation/template.vue
new file mode 100644
index 000000000000..26f7b0381407
--- /dev/null
+++ b/tests/vue/interpolation/template.vue
@@ -0,0 +1,10 @@
+<template>
+  <root>
+<div class="red">
+    We are going to add this simple card here
+  </div>
+  <div class="red">
+    What is going on {{ prop1 }} and {{ prop2 }}
+  </div>
+  </root>
+</template>
diff --git a/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap b/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap
index 5c3ca3a346b8..06754d65f3b5 100644
--- a/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/vue/vue/__snapshots__/jsfmt.spec.js.snap
@@ -1914,9 +1914,7 @@ semi: false
     <template>
       <div></div>
     </template>
-    <div>
-      Do not go out, you'll got yourself cloned by bad bad people.
-    </div>
+    <div>Do not go out, you'll got yourself cloned by bad bad people.</div>
   </div>
 </template>
 
@@ -1947,9 +1945,7 @@ trailingComma: "none"
     <template>
       <div></div>
     </template>
-    <div>
-      Do not go out, you'll got yourself cloned by bad bad people.
-    </div>
+    <div>Do not go out, you'll got yourself cloned by bad bad people.</div>
   </div>
 </template>
 
@@ -1979,9 +1975,7 @@ printWidth: 80
     <template>
       <div></div>
     </template>
-    <div>
-      Do not go out, you'll got yourself cloned by bad bad people.
-    </div>
+    <div>Do not go out, you'll got yourself cloned by bad bad people.</div>
   </div>
 </template>
 
@@ -3127,9 +3121,7 @@ semi: false
         <template v-if="fileSize > 0">
           {{ fileSizeReadable }}
         </template>
-        <template v-if="fileSize > 0 && width && height">
-          |
-        </template>
+        <template v-if="fileSize > 0 && width && height"> | </template>
         <template v-if="width && height">
           W: {{ width }} | H: {{ height }}
         </template>
@@ -3193,9 +3185,7 @@ trailingComma: "none"
         <template v-if="fileSize > 0">
           {{ fileSizeReadable }}
         </template>
-        <template v-if="fileSize > 0 && width && height">
-          |
-        </template>
+        <template v-if="fileSize > 0 && width && height"> | </template>
         <template v-if="width && height">
           W: {{ width }} | H: {{ height }}
         </template>
@@ -3258,9 +3248,7 @@ printWidth: 80
         <template v-if="fileSize > 0">
           {{ fileSizeReadable }}
         </template>
-        <template v-if="fileSize > 0 && width && height">
-          |
-        </template>
+        <template v-if="fileSize > 0 && width && height"> | </template>
         <template v-if="width && height">
           W: {{ width }} | H: {{ height }}
         </template>