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

Issue:
svelteBracketNewLine: false not working
After the update to v2, I added `svelteBracketNewLine: false` to my Prettier config as I prefer the previous formatting. This setting seems to be ignored though. Prettier now closes multiline tags on a new line regardless. Here's my full config:

```yml
# .prettierrc.yml
semi: false
singleQuote: true
svelteBracketNewLine: false
overrides:
  - files: '*.svelte'
    options:
      printWidth: 90
```

![diff](https://user-images.githubusercontent.com/30958850/103872128-440b2c00-50ce-11eb-8740-c01192d8b754.png)


Pull request:
(fix) svelteBracketNewLine closing > print adjustment
When `svelteBracketNewLine` is set to `false`, don't print the closing `>` in a separate line if possible
Fixes #183

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2b8048..7ba1c86 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # prettier-plugin-svelte changelog
 
+## 2.0.3 (Unreleased)
+
+* When `svelteBracketNewLine` is set to `false`, don't print the closing `>` in a separate line if possible ([#183](https://github.com/sveltejs/prettier-plugin-svelte/issues/183))
+
 ## 2.0.2
 
 * Fix formatting of `<template>` tags with an unsupported language inside
diff --git a/src/print/index.ts b/src/print/index.ts
index f45a90f..d4bca62 100644
--- a/src/print/index.ts
+++ b/src/print/index.ts
@@ -31,6 +31,7 @@ import {
     trimChildren,
     trimTextNodeLeft,
     trimTextNodeRight,
+    canOmitSoftlineBeforeClosingTag,
 } from './node-helpers';
 import {
     ASTNode,
@@ -266,7 +267,10 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
                 return groupConcat([
                     ...openingTag,
                     group(indent(concat([softline, groupConcat(['>', body(), `</${node.name}`])]))),
-                    isEmpty && options.svelteBracketNewLine ? '' : softline,
+                    (isEmpty && options.svelteBracketNewLine) ||
+                    canOmitSoftlineBeforeClosingTag(node, path, options)
+                        ? ''
+                        : softline,
                     '>',
                 ]);
             }
@@ -320,7 +324,7 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
                             concat([noHugSeparatorStart, groupConcat([body(), `</${node.name}`])]),
                         ),
                     ),
-                    softline,
+                    canOmitSoftlineBeforeClosingTag(node, path, options) ? '' : '',
                     '>',
                 ]);
             }
diff --git a/src/print/node-helpers.ts b/src/print/node-helpers.ts
index 4f0af14..8d41bb0 100644
--- a/src/print/node-helpers.ts
+++ b/src/print/node-helpers.ts
@@ -410,3 +410,41 @@ export function isInsideQuotedAttribute(path: FastPath, options: ParserOptions):
             (!isLoneMustacheTag(node.value) || options.svelteStrictMode),
     );
 }
+
+/**
+ * Returns true if the softline between `</tagName` and `>` can be omitted.
+ */
+export function canOmitSoftlineBeforeClosingTag(
+    node: Node,
+    path: FastPath,
+    options: ParserOptions,
+): boolean {
+    return (
+        !options.svelteBracketNewLine &&
+        (!hugsStartOfNextNode(node, options) || isLastChildWithinParentBlockElement(path))
+    );
+}
+
+/**
+ * Return true if given node does not hug the next node, meaning there's whitespace
+ * or the end of the doc afterwards.
+ */
+function hugsStartOfNextNode(node: Node, options: ParserOptions): boolean {
+    if (node.end === options.originalText.length) {
+        // end of document
+        return false;
+    }
+
+    return !options.originalText.substring(node.end).match(/^\s/);
+}
+
+function isLastChildWithinParentBlockElement(path: FastPath): boolean {
+    const parent = path.getParentNode() as Node | undefined;
+    if (!parent || !isBlockElement(parent)) {
+        return false;
+    }
+
+    const children = getChildren(parent);
+    const lastChild = children[children.length - 1];
+    return lastChild === path.getNode();
+}


Test patch:
diff --git a/test/formatting/samples/inline-element-break-long-nonewline/input.html b/test/formatting/samples/inline-element-break-long-nonewline/input.html
new file mode 100644
index 0000000..9b8e795
--- /dev/null
+++ b/test/formatting/samples/inline-element-break-long-nonewline/input.html
@@ -0,0 +1,1 @@
+<span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span> <span>hi</span><div><span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span><span>hi</span> <span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span></div> <span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span>
\ No newline at end of file
diff --git a/test/formatting/samples/inline-element-break-long-nonewline/options.json b/test/formatting/samples/inline-element-break-long-nonewline/options.json
new file mode 100644
index 0000000..062715f
--- /dev/null
+++ b/test/formatting/samples/inline-element-break-long-nonewline/options.json
@@ -0,0 +1,3 @@
+{
+    "svelteBracketNewLine": false
+}
diff --git a/test/formatting/samples/inline-element-break-long-nonewline/output.html b/test/formatting/samples/inline-element-break-long-nonewline/output.html
new file mode 100644
index 0000000..ee58ad3
--- /dev/null
+++ b/test/formatting/samples/inline-element-break-long-nonewline/output.html
@@ -0,0 +1,23 @@
+<span
+    ><span>looooooooooong</span
+    >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
+        ><span>hi</span><span>hi</span></span
+    ></span> <span>hi</span>
+<div>
+    <span
+        ><span>looooooooooong</span
+        >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
+            ><span>hi</span><span>hi</span></span
+        ></span
+    ><span>hi</span>
+    <span
+        ><span>looooooooooong</span
+        >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
+            ><span>hi</span><span>hi</span></span
+        ></span>
+</div>
+<span
+    ><span>looooooooooong</span
+    >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
+        ><span>hi</span><span>hi</span></span
+    ></span>
diff --git a/test/formatting/samples/inline-element-break-long/input.html b/test/formatting/samples/inline-element-break-long/input.html
index 0adaef7..9b8e795 100644
--- a/test/formatting/samples/inline-element-break-long/input.html
+++ b/test/formatting/samples/inline-element-break-long/input.html
@@ -1,1 +1,1 @@
-<span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span>
\ No newline at end of file
+<span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span> <span>hi</span><div><span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span><span>hi</span> <span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span></div> <span><span>looooooooooong</span>looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span><span>hi</span><span>hi</span></span></span>
\ No newline at end of file
diff --git a/test/formatting/samples/inline-element-break-long/output.html b/test/formatting/samples/inline-element-break-long/output.html
index a4d094a..1c3ecc9 100644
--- a/test/formatting/samples/inline-element-break-long/output.html
+++ b/test/formatting/samples/inline-element-break-long/output.html
@@ -1,3 +1,23 @@
+<span
+    ><span>looooooooooong</span
+    >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
+        ><span>hi</span><span>hi</span></span
+    ></span
+> <span>hi</span>
+<div>
+    <span
+        ><span>looooooooooong</span
+        >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
+            ><span>hi</span><span>hi</span></span
+        ></span
+    ><span>hi</span>
+    <span
+        ><span>looooooooooong</span
+        >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
+            ><span>hi</span><span>hi</span></span
+        ></span
+    >
+</div>
 <span
     ><span>looooooooooong</span
     >looooooooooonglooooooooooonglooooooooooonglooooooooooonglooooooooooong<span
diff --git a/test/printer/samples/empty-elements-no-newline.html b/test/printer/samples/empty-elements-no-newline.html
index 1751c7a..bcfbae8 100644
--- a/test/printer/samples/empty-elements-no-newline.html
+++ b/test/printer/samples/empty-elements-no-newline.html
@@ -4,8 +4,7 @@
 
 <span
     class="some classsome classsome classsome classsome classsome classsome classsome classsome classsome classsome classsome classsome class"
-    ></span
->
+    ></span>
 
 <span
     class="some classsome classsome classsome classsome classsome classsome classsome classsome classsome classsome classsome classsome class">