prettier: Ugly line break in a template string

Not really an error, but in my opinion, ugly.

Input:

const description =
  `The value of the ${cssName} css of the ${this._name} element`;

Output:

const description = `The value of the ${cssName} css of the ${this
  ._name} element`;

Expected:

const description = `The value of the ${cssName} css of the ${
  this._name
} element`;

Or something like that…

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 26
  • Comments: 28 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Maybe templates should never be wrapped because it looks ugly most of time.

This input

const description =
  `The value of the ${cssName} css of the ${this._name} element`;

looks better that

const description = `The value of the ${cssName} css of the ${
  this._name
} element`;

even if it’s longer than the max col limit

Example prettier version 2.3.0 playground link

logger.info(`Creating new '${subject.toString()}' report from camera '${camera.name}'`);

got converted to:

logger.info(
  `Creating new '${subject.toString()}' report from camera '${
    camera.name
  }'`
);

which is way uglier

Any news on this one? Still happening on versions 1.15.0 and 1.16.0.

Prettier 1.16.0 Playground link

--parser typescript

Input:

const BASE_URL: string = `http://${process.env.VERY_LONG_VARIABLE || 'localhost'}:3001`;

Output:

const BASE_URL: string = `http://${process.env.VERY_LONG_VARIABLE ||
  "localhost"}:3001`;

Expected behavior:

const BASE_URL: string = 
  `http://${process.env.VERY_LONG_VARIABLE || 'localhost'}:3001`;

The string in the expected behavior is in the print width range (80).

I used git bisect to determine the commit where this behaviour changed:

commit 374a68201c966ee9064a1173f5dfeb37980cfbe3 (pr #1664) Author: Joseph Frazier 1212jtraceur@gmail.com Date: Mon May 22 12:00:01 2017 -0400

Don't removeLines() from TemplateLiteral quasis (#1664)

* Add tests for newlines in template literals

These are related to the following issues:

* https://github.com/prettier/prettier/issues/1662
* https://github.com/prettier/prettier/issues/821
* https://github.com/prettier/prettier/issues/1183
* https://github.com/prettier/prettier/issues/1626

* Don't removeLines() from TemplateLiteral quasis

This fixes https://github.com/prettier/prettier/issues/1662
and fixes https://github.com/prettier/prettier/issues/1626

It also affects https://github.com/prettier/prettier/issues/821 and
https://github.com/prettier/prettier/issues/1183

The code change was in src/printer.js:

@@ -1672,11 +1672,7 @@ function genericPrintNoParens(path, options, print, args) {
             size = util.getAlignmentSize(value, tabWidth, index + 1);
           }

-          const aligned = addAlignmentToDoc(
-            removeLines(expressions[i]),
-            size,
-            tabWidth
-          );
+          const aligned = addAlignmentToDoc(expressions[i], size, tabWidth);

           parts.push("${", aligned, lineSuffixBoundary, "}");
         }

Personally I would like to see this changed.

Here is the example I was testing:

const foo = `such a long template string ${foo.bar.baz} that prettier will want to wrap it`;

which now becomes

const foo = `such a long template string ${foo.bar
  .baz} that prettier will want to wrap it`;

Which definitely seems like a bug to me, I don’t think prettier should wrap inside of template strings.

Why is this closed - it’s still a problem.

Here’s another example that formats poorly:

const initials = `${profile.givenName.charAt(0)}${profile.familyName.charAt(
  0
)}`;

I think this is my biggest gripe with Prettier. Everything else has been spectacular. Wish this was not dismissed.

I agree @Skywalker13, such strings should never wrap.

What if we just never break ‘simple’ expressions in template strings? The definition of simple is TBD unless there’s a precedence in Prettier already. Off the cuff:

  • Identifiers
  • Property access
  • Ternaries or BinaryExpressions, where each node is one of the above

Or instead the line could be drawn at the other end. Don’t break unless for:

  • Functions
  • Object/Array literals
  • ?

What seems to be difficult is telling the difference between graphql and css-in-js, where breaks are encouraged from what I can tell, and situations like user-facing strings and regexes, where breaks hurt readability and lead to more WTFs/min. So another option could be adding a blanket don’t-break-expressions rule for template strings, and adding special casing for these libraries.

I am now personally of the belief that prettier should respect existing formatting within template strings.

We actually experimented just printing the string as is, but people complained that prettier didn’t change ’ to " and format their code.

The current status is not ideal for sure, we’ll keep iterating on it. I do believe that we can get it to work well for most use cases. We’re just not 100% there yet (but getting way better in each version of prettier).

ok I think I understand what we’re seeing now. Thanks - I’m getting what looks like a format due to the length of my string.

This is closed because the code in the original post now formats as expected:

Prettier 1.16.4 Playground link

--parser babylon

Input:

const description =
  `The value of the ${cssName} css of the ${this._name} element`;

Output:

const description = `The value of the ${cssName} css of the ${
  this._name
} element`;

If you have a different example that doesn’t format nicely, please open a new issue.

I know they look very similar but internally these are different code paths and if we aren’t specific with this type of work, it’s easy to get lost or miscommunicate.

@DorZion could you open a new issue for your example?

Yes, in the source code; it’s the case between v1.3.x and v1.4.x. It was looking better with v1.3.x.

Do i understand correctly, that wrapping also adds new line characters? If so, then it can break some formatting when someone not expecting additional newline there, doesnt it?