Repository: sveltejs/prettier-plugin-svelte
Pull request #186 (2021-01-07 17:19:53)

(fix) better formatting of template tags


Patch:
diff --git a/src/print/index.ts b/src/print/index.ts
index bc039a0..f45a90f 100644
--- a/src/print/index.ts
+++ b/src/print/index.ts
@@ -224,7 +224,7 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
             } else if (isPreTagContent(path)) {
                 body = () => printRaw(node, options.originalText);
             } else if (!isSupportedLanguage) {
-                body = () => printRaw(node, options.originalText);
+                body = () => printRaw(node, options.originalText, true);
                 hugContent = true;
             } else if (isInlineElement(path, node) && !isPreTagContent(path)) {
                 body = () => printChildren(path, print);
@@ -250,6 +250,18 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
                 ),
             ];
 
+            if (!isSupportedLanguage && !isEmpty) {
+                // Format template tags so that there's a hardline but no intendation.
+                // That way the `lang="X"` and the closing `>` of the start tag stay in one line
+                // which is the 99% use case.
+                return groupConcat([
+                    ...openingTag,
+                    '>',
+                    groupConcat([hardline, body(), hardline]),
+                    `</${node.name}>`,
+                ]);
+            }
+
             if (hugStart && hugEnd) {
                 return groupConcat([
                     ...openingTag,
diff --git a/src/print/node-helpers.ts b/src/print/node-helpers.ts
index e329fef..4f0af14 100644
--- a/src/print/node-helpers.ts
+++ b/src/print/node-helpers.ts
@@ -100,6 +100,7 @@ export function isIgnoreDirective(node: Node | undefined | null): boolean {
 export function printRaw(
     node: ElementNode | InlineComponentNode | SlotNode | WindowNode | HeadNode | TitleNode,
     originalText: string,
+    stripLeadingAndTrailingNewline: boolean = false,
 ): string {
     if (node.children.length === 0) {
         return '';
@@ -107,7 +108,24 @@ export function printRaw(
 
     const firstChild = node.children[0];
     const lastChild = node.children[node.children.length - 1];
-    return originalText.substring(firstChild.start, lastChild.end);
+
+    let raw = originalText.substring(firstChild.start, lastChild.end);
+
+    if (!stripLeadingAndTrailingNewline) {
+        return raw;
+    }
+
+    if (startsWithLinebreak(raw)) {
+        raw = raw.substring(raw.indexOf('\n') + 1);
+    }
+    if (endsWithLinebreak(raw)) {
+        raw = raw.substring(0, raw.lastIndexOf('\n'));
+        if (raw.charAt(raw.length - 1) === '\r') {
+            raw = raw.substring(0, raw.length - 1);
+        }
+    }
+
+    return raw;
 }
 
 function isTextNode(node: Node): node is TextNode {


Test patch:
diff --git a/test/printer/samples/template-empty-with-url.html b/test/printer/samples/template-empty-with-url.html
new file mode 100644
index 0000000..50977cc
--- /dev/null
+++ b/test/printer/samples/template-empty-with-url.html
@@ -0,0 +1,1 @@
+<template lang="pug" src="./some.pug"></template>
diff --git a/test/printer/samples/template-empty-with-url.options.json b/test/printer/samples/template-empty-with-url.options.json
new file mode 100644
index 0000000..7149251
--- /dev/null
+++ b/test/printer/samples/template-empty-with-url.options.json
@@ -0,0 +1,3 @@
+{
+    "svelteStrictMode": true
+}
diff --git a/test/printer/samples/template-pug.html b/test/printer/samples/template-pug.html
new file mode 100644
index 0000000..4f48e9e
--- /dev/null
+++ b/test/printer/samples/template-pug.html
@@ -0,0 +1,16 @@
+<template lang="pug">
+    - var user = {'foo bar baz'}
+  - var authorised = false
+  #user
+  if user.description
+    h2.green Description
+    p.description= user.description
+  else if authorised
+    h2.blue Description
+    p.description.
+      User has no description,
+      why not add one...
+  else
+    h2.red Description
+    p.description User has no description
+</template>