diff --git a/.eslintrc.yml b/.eslintrc.yml
index 255da117716a..52280121c79e 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -3,24 +3,24 @@ env:
es6: true
node: true
extends:
-- eslint:recommended
-- plugin:react/recommended
-- plugin:prettier/recommended
+ - eslint:recommended
+ - plugin:react/recommended
+ - plugin:prettier/recommended
plugins:
-- import
+ - import
rules:
curly: error
import/no-extraneous-dependencies:
- - error
- - devDependencies: ["tests*/**", "scripts/**"]
+ - error
+ - devDependencies: ["tests*/**", "scripts/**"]
no-else-return: error
no-inner-declarations: error
no-unneeded-ternary: error
no-useless-return: error
no-var: error
one-var:
- - error
- - never
+ - error
+ - never
prefer-arrow-callback: error
prefer-const: error
react/display-name: off
@@ -29,6 +29,6 @@ rules:
strict: error
symbol-description: error
yoda:
- - error
- - never
- - exceptRange: true
+ - error
+ - never
+ - exceptRange: true
diff --git a/.ignore b/.ignore
index bacdd589fbc6..a6920dce0114 100644
--- a/.ignore
+++ b/.ignore
@@ -1,3 +1,2 @@
website/static/lib
dist
-
diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md
index 229fc486b5c6..34e0a3a00d2e 100644
--- a/CHANGELOG.unreleased.md
+++ b/CHANGELOG.unreleased.md
@@ -44,9 +44,243 @@ const link = http://example.com;
-->
-#### TypeScript: Print comment following a JSX element with generic ([#6209] by [@duailibe])
+#### API: add resolveConfig option to getFileInfo() ([#6666] by [@kaicataldo])
-Previous versions would not print this comment, this has been fixed in this version.
+Add a `resolveConfig: boolean` option to `prettier.getFileInfo()` that, when set to `true`, will resolve the configuration for the given file path. This allows consumers to take any overridden parsers into account.
+
+#### JavaScript: add support for PartialApplication ([#6397] by [@JounQin])
+
+Previous versions would not be able to format this syntax, this has been fixed in this version.
+
+
+```js
+const addOne = add(1, ?); // apply from the left
+addOne(2); // 3
+
+const addTen = add(?, 10); // apply from the right
+addTen(2); // 12
+
+// with pipeline
+let newScore = player.score
+ |> add(7, ?)
+ |> clamp(0, 100, ?); // shallow stack, the pipe to `clamp` is the same frame as the pipe to `add`.
+
+// Output (Prettier stable)
+SyntaxError: Unexpected token (1:23)
+> 1 | const addOne = add(1, ?); // apply from the left
+ | ^
+ 2 | addOne(2); // 3
+ 3 |
+ 4 | const addTen = add(?, 10); // apply from the right
+
+// Output (Prettier master)
+const addOne = add(1, ?); // apply from the left
+addOne(2); // 3
+
+const addTen = add(?, 10); // apply from the right
+addTen(2); // 12
+
+// with pipeline
+let newScore = player.score |> add(7, ?) |> clamp(0, 100, ?); // shallow stack, the pipe to \`clamp\` is the same frame as the pipe to \`add\`.
+```
+
+#### JavaScript: More readable parentheses for new-call ([#6412] by [@bakkot])
+
+
+```js
+// Input
+var a = new (x().y)();
+var a = new (x().y.z)();
+var a = new (x().y().z)();
+
+// Output (Prettier stable)
+var a = new (x()).y();
+var a = new (x()).y.z();
+var a = new (x().y()).z();
+
+// Output (Prettier master)
+var a = new (x().y)();
+var a = new (x().y.z)();
+var a = new (x().y().z)();
+```
+
+#### MDX: Text following JSX was trimmed incorrectly ([#6340] by [@JounQin])
+
+
+```md
+
+# Heading
+
+ test test
+ 123
+
+
+
+ test test
+123
+
+
+
+ test test
+ 123
+```
+
+#### TypeScript/Flow: Fix indentation for union types inside tuples ([#6381] by [@squidfunk], [#6605] by [@thorn0])
+
+
+```ts
+// Input
+type A = [
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+]
+
+type B = [
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD,
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+]
+
+type C = [
+ | [AAAAAAAAAAAAAAAAAAAAAA | BBBBBBBBBBBBBBBBBBBBBB | CCCCCCCCCCCCCCCCCCCCCC | DDDDDDDDDDDDDDDDDDDDDD]
+ | [AAAAAAAAAAAAAAAAAAAAAA | BBBBBBBBBBBBBBBBBBBBBB | CCCCCCCCCCCCCCCCCCCCCC | DDDDDDDDDDDDDDDDDDDDDD]
+]
+
+// Output (Prettier stable)
+type A = [
+
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+];
+
+type B = [
+
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD,
+
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+];
+
+type C = [
+
+ | [
+
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+ ]
+ | [
+
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+ ]
+];
+
+// Output (Prettier master)
+type A = [
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+];
+
+type B = [
+ (
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+ ),
+ (
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+ )
+];
+
+type C = [
+ | [
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+ ]
+ | [
+ | AAAAAAAAAAAAAAAAAAAAAA
+ | BBBBBBBBBBBBBBBBBBBBBB
+ | CCCCCCCCCCCCCCCCCCCCCC
+ | DDDDDDDDDDDDDDDDDDDDDD
+ ]
+];
+```
+
+#### MDX: Adjacent JSX elements should be allowed ([#6332] by [@JounQin])
+
+
+```jsx
+// Input
+
+ test test
+123
+
+// Output (Prettier stable)
+SyntaxError: Unexpected token (3:9)
+ 1 |
+ 2 | test test
+> 3 | 123
+ | ^
+
+// Output (Prettier master)
+
+ test test
+123
+
+
+// Input
+
+ test test
+
+
+ test test
+123
+
+// Output (Prettier stable)
+SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...>? (4:1)
+ 2 | test test
+ 3 |
+> 4 |
+ | ^
+ 5 | test test
+ 6 | 123
+
+// Output (Prettier master)
+
+ test test
+
+
+ test test
+123
+```
+
+#### TypeScript: Comments after JSX element names with type arguments were lost ([#6209] by [@duailibe])
```ts
@@ -74,7 +308,7 @@ const comp = (
);
```
-### Handlebars: Avoid adding unwanted line breaks between text and mustaches ([#6186] by [@gavinjoyce])
+#### Handlebars: Avoid adding unwanted line breaks between text and mustaches ([#6186] by [@gavinjoyce])
Previously, Prettier added line breaks between text and mustaches which resulted in unwanted whitespace in rendered output.
@@ -104,7 +338,7 @@ Previously, Prettier added line breaks between text and mustaches which resulted
```
-### Handlebars: Improve comment formatting ([#6206] by [@gavinjoyce])
+#### Handlebars: Improve comment formatting ([#6206] by [@gavinjoyce])
Previously, Prettier would sometimes ignore whitespace when formatting comments.
@@ -146,9 +380,25 @@ Previously, Prettier would sometimes ignore whitespace when formatting comments.
```
-#### JavaScript: Keep unary expressions parentheses with comments ([#6217] by [@sosukesuzuki])
+#### JavaScript: Update ?? precedence to match stage 3 proposal ([#6404] by [@vjeux])
-Previously, Prettier removes parentheses enclose unary expressions. This change modify to keep it when the expression has comments.
+We've updated Prettier's support for the nullish coalescing operator to match a spec update that no longer allows it to immediately contain, or be contained within an `&&` or `||` operation.
+
+
+```js
+// Input
+(foo ?? baz) || baz;
+
+// Output (Prettier stable)
+foo ?? baz || baz;
+
+// Output (Prettier master)
+(foo ?? baz) || baz;
+```
+
+Please note, as we update our parsers with versions that support this spec update, code without the parenthesis will throw a parse error.
+
+#### JavaScript: Keep parentheses with comments in unary expressions ([#6217] by [@sosukesuzuki])
```ts
@@ -173,9 +423,58 @@ foo;
);
```
-### Handlebars: Improve comment formatting ([#6234] by [@gavinjoyce])
+#### Javascript: Use function literals in arguments to detect function composition ([#6033] by [@brainkim])
-Previously, Prettier would incorrectly decode HTML entiites.
+Previously, we used a set of hard-coded names related to functional programming
+(`compose`, `flow`, `pipe`, etc.) to detect function composition and chaining
+patterns in code. This was done so that Prettier would not put code like the
+following call to `pipe` on the same line even if it fit within the allotted
+column budget:
+
+
+```js
+source$
+ .pipe(
+ filter(x => x % 2 === 0),
+ map(x => x + x),
+ scan((acc, x) => acc + x, 0),
+ )
+ .subscribe(x => console.log(x));
+```
+
+However, this heuristic caused people to complain because of false positives
+where calls to functions or methods matching the hard-coded names would always
+be split on multiple lines, even if the calls did not contain function
+arguments (https://github.com/prettier/prettier/issues/5769,
+https://github.com/prettier/prettier/issues/5969). For many, this blanket
+decision to split functions based on name was both surprising and sub-optimal.
+
+We now use a refined heuristic which uses the presence of function literals to
+detect function composition. This heuristic preserves the line-splitting
+behavior above and eliminates many if not all of the false positives caused by
+the older heuristic.
+
+We encourage prettier users to try out the new heuristic and provide feedback.
+
+
+```js
+// Input
+eventStore.update(id, _.flow(updater, incrementVersion));
+
+// Output (Prettier stable)
+eventStore.update(
+ id,
+ _.flow(
+ updater,
+ incrementVersion
+ )
+);
+
+// Output (Prettier master)
+eventStore.update(id, _.flow(updater, incrementVersion));
+```
+
+#### Handlebars: Preserve HTML entities ([#6234] by [@gavinjoyce])
```hbs
@@ -197,8 +496,6 @@ Previously, Prettier would incorrectly decode HTML entiites.
#### JavaScript: Stop moving comments inside tagged template literals ([#6236] by [@sosukesuzuki])
-Previously, Prettier would move comments after the tag inside the template literal. This version fixes this problem.
-
```js
// Input
@@ -216,9 +513,10 @@ foo // comment
`;
```
-#### JavaScript: Fix moving comments in function calls like `useEffect` second argument ([#6270] by [@sosukesuzuki])
+#### TypeScript/Flow: Fix moving comments in function calls like `useEffect` ([#6270] by [@sosukesuzuki])
-This fixes a bug that was affecting function calls that have a arrow function as first argument and an array expression as second argument, such as the common React's `useEffect`. A comment in its own line before the second argument would be moved to the line above.
+This fixes a bug that was affecting function calls with an arrow function as the first argument and an array expression as the second argument, e.g. React's `useEffect`.
+If a comment was placed on the line before the second argument, Prettier would move it to the line above and corrupt the indentation.
The bug was only present when using the Flow and TypeScript parsers.
@@ -230,18 +528,14 @@ useEffect(
console.log("some code", props.foo);
},
- // We need to disable the eslint warning here,
- // because of some complicated reason.
- // eslint-disable line react-hooks/exhaustive-deps
+ // eslint-disable-line react-hooks/exhaustive-deps
[]
);
// Output (Prettier stable)
useEffect(() => {
console.log("some code", props.foo);
-}, // We need to disable the eslint warning here,
-// because of some complicated reason.
-// eslint-disable line react-hooks/exhaustive-deps
+}, // eslint-disable-line react-hooks/exhaustive-deps
[]);
// Output (Prettier master)
@@ -250,9 +544,7 @@ useEffect(
console.log("some code", props.foo);
},
- // We need to disable the eslint warning here,
- // because of some complicated reason.
- // eslint-disable line react-hooks/exhaustive-deps
+ // eslint-disable-line react-hooks/exhaustive-deps
[]
);
```
@@ -261,6 +553,540 @@ useEffect(
This version updates the TypeScript parser to correctly handle JSX text with double slashes (`//`). In previous versions, this would cause Prettier to crash.
+#### HTML, Vue: Don't wrap `template` elements on lines shorter than `printWidth` ([#6284] by [@sosukesuzuki])
+
+Previously, even if the line length was shorter than `printWidth`, Prettier would break the line with a `template` element.
+
+
+```html
+// Input
+
+ foo
+
+
+// Output (Prettier stable)
+
+ foo
+
+
+// Output (Prettier master)
+
+ foo
+
+```
+
+#### JavaScript: Fix breaks indentation and idempotency when an arrow function that args include object pattern is passed to a function as parameter. ([#6301] & [#6382] by [@sosukesuzuki])
+
+Previously, Prettier indented code strangely when an arrow function whose parameters included an object pattern was passed to a function call as an argument. Also, it broke idempotence. Please see [#6294](https://github.com/prettier/prettier/issues/6294) for details.
+
+
+```js
+// Input
+foo(
+ ({
+ a,
+
+ b
+ }) => {}
+);
+
+// Output (Prettier stable)
+foo(({ a,
+ b }) => {});
+
+// Output (Prettier master)
+foo(
+ ({
+ a,
+
+ b
+ }) => {}
+);
+```
+
+#### TypeScript: Put a closing parenthesis onto a new line after union types ([#6307] by [@sosukesuzuki])
+
+
+```ts
+// Input
+const foo = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (
+ | string
+ | undefined
+)[];
+
+// Prettier (stable)
+const foo = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (
+ | string
+ | undefined)[];
+
+// Prettier (master)
+const foo = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (
+ | string
+ | undefined
+)[];
+```
+
+#### HTML: Script tags are now treated as blocks for the purposes of formatting ([#6423] by [@thorn0])
+
+Previously, in the [whitespace-sensitive mode](https://prettier.io/docs/en/options.html#html-whitespace-sensitivity), they were formatted as if they were inline.
+
+
+```html
+
+
+
+
+
+
+
+
+
+```
+
+#### TypeScript: Correctly format long one-line mapped types in one pass ([#6420] by [@sosukesuzuki])
+
+Previously, when Prettier formatted long one-line mapped types, it would break the line but didn’t add a semicolon until you ran Prettier again, which means Prettier’s idempotence rule was broken. Now, Prettier adds the semicolon in the first run.
+
+
+```ts
+// Input
+type FooBar = { [P in keyof T]: T[P] extends Something ? Something : T[P] }
+
+// Prettier (stable)
+type FooBar = {
+ [P in keyof T]: T[P] extends Something ? Something : T[P]
+};
+
+// Prettier (master)
+type FooBar = {
+ [P in keyof T]: T[P] extends Something ? Something : T[P];
+};
+```
+
+#### JavaScript: Fix formatting of object destructuring with parameter decorators ([#6411] by [@sosukesuzuki])
+
+Previously, Prettier formatted decorators for destructured parameters in a weird way. Now, parameter decorators are placed just above the parameter they belong to.
+
+
+```js
+// Input
+class Class {
+ method(
+ @decorator
+ { foo }
+ ) {}
+}
+
+// Prettier (stable)
+class Class {
+ method(@decorator
+ {
+ foo
+ }) {}
+}
+
+// Prettier (master)
+class Class {
+ method(
+ @decorator
+ { foo }
+ ) {}
+}
+```
+
+#### JavaScript: Handle empty object patterns with type annotations in function parameters ([#6438] by [@bakkot])
+
+
+```js
+// Input
+const f = ({}: MyVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongType) => {};
+function g({}: Foo) {}
+
+// Output (Prettier stable)
+const f = ({
+ ,
+}: MyVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongType) => {};
+function g({ }: Foo) {}
+
+// Output (Prettier master)
+const f = ({}: MyVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongType) => {};
+function g({}: Foo) {}
+```
+
+#### JavaScript: Put a closing parenthesis onto a new line after binary expressions within function calls ([#6441] by [@sosukesuzuki])
+
+
+```js
+// Input
+(
+ aaaaaaaaaaaaaaaaaaaaaaaaa &&
+ bbbbbbbbbbbbbbbbbbbbbbbbb &&
+ ccccccccccccccccccccccccc &&
+ ddddddddddddddddddddddddd &&
+ eeeeeeeeeeeeeeeeeeeeeeeee
+)();
+
+// Prettier (stable)
+(aaaaaaaaaaaaaaaaaaaaaaaaa &&
+ bbbbbbbbbbbbbbbbbbbbbbbbb &&
+ ccccccccccccccccccccccccc &&
+ ddddddddddddddddddddddddd &&
+ eeeeeeeeeeeeeeeeeeeeeeeee)();
+
+// Prettier (master)
+(
+ aaaaaaaaaaaaaaaaaaaaaaaaa &&
+ bbbbbbbbbbbbbbbbbbbbbbbbb &&
+ ccccccccccccccccccccccccc &&
+ ddddddddddddddddddddddddd &&
+ eeeeeeeeeeeeeeeeeeeeeeeee
+)();
+```
+
+#### JavaScript: Fix formatting of long named exports ([#6446] by [@sosukesuzuki])
+
+Now, Prettier formats them the same way it formats named imports.
+
+
+```js
+// Input
+export { fooooooooooooooooooooooooooooooooooooooooooooooooo } from "fooooooooooooooooooooooooooooo";
+
+// Prettier (stable)
+export {
+ fooooooooooooooooooooooooooooooooooooooooooooooooo
+} from "fooooooooooooooooooooooooooooo";
+
+// Prettier (master)
+export { fooooooooooooooooooooooooooooooooooooooooooooooooo } from "fooooooooooooooooooooooooooooo";
+```
+
+#### JavaScript: Fix bad formatting for multi-line optional chaining with comment ([#6506] by [@sosukesuzuki])
+
+
+```js
+// Input
+return a
+ .b()
+ .c()
+ // Comment
+ ?.d()
+
+// Prettier (stable)
+return a
+ .b()
+ .c()
+ ?.// Comment
+ d();
+
+// Prettier (master)
+return (
+ a
+ .b()
+ .c()
+ // Comment
+ ?.d()
+);
+```
+
+#### JavaScript: Fix inconsistent indentation in switch statement ([#6514] by [@sosukesuzuki])
+
+
+```js
+// Input
+switch ($veryLongAndVeryVerboseVariableName && $anotherVeryLongAndVeryVerboseVariableName) {
+}
+
+switch ($longButSlightlyShorterVariableName && $anotherSlightlyShorterVariableName) {
+}
+
+// Prettier (stable)
+switch (
+ $veryLongAndVeryVerboseVariableName &&
+ $anotherVeryLongAndVeryVerboseVariableName
+) {
+}
+
+switch (
+ $longButSlightlyShorterVariableName && $anotherSlightlyShorterVariableName
+) {
+}
+
+// Prettier (master)
+switch (
+ $veryLongAndVeryVerboseVariableName &&
+ $anotherVeryLongAndVeryVerboseVariableName
+) {
+}
+
+switch (
+ $longButSlightlyShorterVariableName &&
+ $anotherSlightlyShorterVariableName
+) {
+}
+```
+
+#### TypeScript: Keep type parameters inline for type annotations in variable declarations ([#6467] by [@sosukesuzuki])
+
+
+```ts
+// Input
+const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc();
+
+// Prettier (stable)
+const fooooooooooooooo: SomeThing<
+ boolean
+> = looooooooooooooooooooooooooooooongNameFunc();
+
+// Prettier (master)
+const fooooooooooooooo: SomeThing = looooooooooooooooooooooooooooooongNameFunc();
+```
+
+#### Handlebars: Fix `--single-quote` option on HTML attributes ([#6377] by [@dcyriller])
+
+Previously, the flag was not applied on HTML attributes.
+
+
+```hbs
+// Input
+
+
+// Prettier (stable with the option --single-quote)
+
+
+// Prettier (master with the option --single-quote)
+
+```
+
+#### TypeScript: Sometimes double parentheses around types were removed incorrectly ([#6604] by [@sosukesuzuki])
+
+
+```ts
+// Input
+type A = 0 extends ((1 extends 2 ? 3 : 4)) ? 5 : 6;
+type B = ((0 extends 1 ? 2 : 3)) extends 4 ? 5 : 6;
+type C = ((number | string))["toString"];
+type D = ((keyof T1))["foo"];
+
+// Prettier (stable)
+type A = 0 extends 1 extends 2 ? 3 : 4 ? 5 : 6;
+type B = 0 extends 1 ? 2 : 3 extends 4 ? 5 : 6;
+type C = number | string["toString"];
+type D = keyof T1["foo"];
+
+// Prettier (master)
+type A = 0 extends (1 extends 2 ? 3 : 4) ? 5 : 6;
+type B = (0 extends 1 ? 2 : 3) extends 4 ? 5 : 6;
+type C = (number | string)["toString"];
+type D = (keyof T1)["foo"];
+```
+
+#### JavaScript: Support formatting code with V8 intrinsics ([#6496] by [@rreverser])
+
+
+```js
+// Input
+function doSmth() {
+ %DebugPrint
+ (
+ foo )
+ }
+
+// Prettier (stable)
+SyntaxError: Unexpected token (2:13)
+ 1 | function doSmth() {
+> 2 | %DebugPrint
+ | ^
+
+// Prettier (master)
+function doSmth() {
+ %DebugPrint(foo);
+}
+```
+
+#### TypeScript: Sometimes removing parentheses around JSX made the code unparseable ([#6640] by [@sosukesuzuki])
+
+
+```tsx
+// Input
+().toString();
+
+// Prettier (stable)
+.toString():
+
+// Prettier (master)
+().toString();
+```
+
+#### JavaScript: Object destructuring in method parameters always broke into multiple lines ([#6646] by [@ericsakmar])
+
+
+```js
+// Input
+const obj = {
+ func(id, { blog: { title } }) {
+ return id + title;
+ },
+};
+
+class A {
+ func(id, { blog: { title } }) {
+ return id + title;
+ }
+ #func(id, { blog: { title } }) {
+ return id + title;
+ }
+}
+
+// Prettier (stable)
+const obj = {
+ func(
+ id,
+ {
+ blog: { title }
+ }
+ ) {
+ return id + title;
+ }
+};
+
+class A {
+ func(
+ id,
+ {
+ blog: { title }
+ }
+ ) {
+ return id + title;
+ }
+ #func(
+ id,
+ {
+ blog: { title }
+ }
+ ) {
+ return id + title;
+ }
+}
+
+// Prettier (master)
+const obj = {
+ func(id, { blog: { title } }) {
+ return id + title;
+ },
+};
+
+class A {
+ func(id, { blog: { title } }) {
+ return id + title;
+ }
+ #func(id, { blog: { title } }) {
+ return id + title;
+ }
+}
+```
+
+#### TypeScript: Fix optional computed methods ([#6673] by [@thorn0])
+
+
+```ts
+// Input
+class A {
+ protected [s]?() {}
+}
+
+// Output (Prettier stable)
+class A {
+ protected [s?]() {}
+}
+
+// Output (Prettier master)
+class A {
+ protected [s]?() {}
+}
+```
+
+#### Angular: Put a closing parenthesis onto a new line after ternaries passed to pipes ([#5682] by [@selvazhagan])
+
+
+```html
+
+{{ (isCustomDiscount ? 'DISCOUNTS__DISCOUNT_TRAINING_HEADER__CUSTOM_DISCOUNT' : 'DISCOUNTS__DISCOUNT_TRAINING_HEADER__DISCOUNT') | translate }}
+
+
+{{
+ (isCustomDiscount
+ ? "DISCOUNTS__DISCOUNT_TRAINING_HEADER__CUSTOM_DISCOUNT"
+ : "DISCOUNTS__DISCOUNT_TRAINING_HEADER__DISCOUNT") | translate
+}}
+
+
+{{
+ (isCustomDiscount
+ ? "DISCOUNTS__DISCOUNT_TRAINING_HEADER__CUSTOM_DISCOUNT"
+ : "DISCOUNTS__DISCOUNT_TRAINING_HEADER__DISCOUNT"
+ ) | translate
+}}
+```
+
+#### Handlebars: Fix handling of whitespace and line breaks ([#6354] by [@chadian])
+
+This fixes a variety of whitespace and line break usecases within handlebars and Glimmer templates.
+
+
+```hbs
+// Input
+{{name}}
+
+Some sentence with {{dynamic}} expressions.
+
+
+
+sometimes{{nogaps}}areimportant
+{{name}} is your name
+
+// Output (Prettier stable)
+
+{{name}}
+Some sentence with
+{{dynamic}}
+expressions.
+
+
+
+sometimes
+{{nogaps}}
+areimportant
+
+{{name}}
+is your name
+
+// Output (Prettier master)
+{{name}}
+
+Some sentence with {{dynamic}} expressions.
+
+
+
+sometimes{{nogaps}}areimportant
+
+{{name}} is your name
+```
+
+[#5910]: https://github.com/prettier/prettier/pull/5910
+[#6033]: https://github.com/prettier/prettier/pull/6033
[#6186]: https://github.com/prettier/prettier/pull/6186
[#6206]: https://github.com/prettier/prettier/pull/6206
[#6209]: https://github.com/prettier/prettier/pull/6209
@@ -268,7 +1094,45 @@ This version updates the TypeScript parser to correctly handle JSX text with dou
[#6234]: https://github.com/prettier/prettier/pull/6234
[#6236]: https://github.com/prettier/prettier/pull/6236
[#6270]: https://github.com/prettier/prettier/pull/6270
+[#6284]: https://github.com/prettier/prettier/pull/6284
[#6289]: https://github.com/prettier/prettier/pull/6289
+[#6301]: https://github.com/prettier/prettier/pull/6301
+[#6307]: https://github.com/prettier/prettier/pull/6307
+[#6332]: https://github.com/prettier/prettier/pull/6332
+[#6340]: https://github.com/prettier/prettier/pull/6340
+[#6377]: https://github.com/prettier/prettier/pull/6377
+[#6381]: https://github.com/prettier/prettier/pull/6381
+[#6397]: https://github.com/prettier/prettier/pull/6397
+[#6404]: https://github.com/prettier/prettier/pull/6404
+[#6411]: https://github.com/prettier/prettier/pull/6411
+[#6412]: https://github.com/prettier/prettier/pull/6412
+[#6420]: https://github.com/prettier/prettier/pull/6420
+[#6423]: https://github.com/prettier/prettier/pull/6423
+[#6438]: https://github.com/prettier/prettier/pull/6411
+[#6441]: https://github.com/prettier/prettier/pull/6441
+[#6446]: https://github.com/prettier/prettier/pull/6446
+[#6467]: https://github.com/prettier/prettier/pull/6467
+[#6496]: https://github.com/prettier/prettier/pull/6496
+[#6506]: https://github.com/prettier/prettier/pull/6506
+[#6514]: https://github.com/prettier/prettier/pull/6514
+[#6604]: https://github.com/prettier/prettier/pull/6604
+[#6605]: https://github.com/prettier/prettier/pull/6605
+[#6640]: https://github.com/prettier/prettier/pull/6640
+[#6646]: https://github.com/prettier/prettier/pull/6646
+[#6673]: https://github.com/prettier/prettier/pull/6673
+[#6382]: https://github.com/prettier/prettier/pull/6382
+[@brainkim]: https://github.com/brainkim
[@duailibe]: https://github.com/duailibe
[@gavinjoyce]: https://github.com/gavinjoyce
[@sosukesuzuki]: https://github.com/sosukesuzuki
+[@g-harel]: https://github.com/g-harel
+[@jounqin]: https://github.com/JounQin
+[@bakkot]: https://gibhub.com/bakkot
+[@thorn0]: https://github.com/thorn0
+[@dcyriller]: https://github.com/dcyriller
+[@rreverser]: https://github.com/RReverser
+[@ericsakmar]: https://github.com/ericsakmar
+[@squidfunk]: https://github.com/squidfunk
+[@vjeux]: https://github.com/vjeux
+[@selvazhagan]: https://github.com/selvazhagan
+[@chadian]: https://github.com/chadian
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 90f8c9a639a9..d29de631f92d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,7 +15,7 @@ Here's what you need to know about the tests:
- You can run `AST_COMPARE=1 jest` for a more robust test run. That formats each file, re-parses it, and compares the new AST with the original one and makes sure they are semantically equivalent.
- Each test folder has a `jsfmt.spec.js` that runs the tests. For JavaScript files, generally you can just put `run_spec(__dirname, ["babel", "flow", "typescript"]);` there. This will verify that the output using each parser is the same. You can also pass options as the third argument, like this: `run_spec(__dirname, ["babel"], { trailingComma: "es5" });`
- `tests/flow/` contains the Flow test suite, and is not supposed to be edited by hand. To update it, clone the Flow repo next to the Prettier repo and run: `node scripts/sync-flow-tests.js ../flow/tests/`.
-- If you would like to debug prettier locally, you can either debug it in node or the browser. The easiest way to debug it in the browser is to run the interactive `docs` REPL locally. The easiest way to debug it in node, is to create a local test file and run it in an editor like VS Code.
+- If you would like to debug prettier locally, you can either debug it in node or the browser. The easiest way to debug it in the browser is to run the interactive `docs` REPL locally. The easiest way to debug it in node, is to create a local test file with some example code you want formatted and either run it in an editor like VS Code or run it directly via `./bin/prettier.js `.
Run `yarn lint --fix` to automatically format files.
diff --git a/docs/api.md b/docs/api.md
index 249d598822d8..a2126dc2753f 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -58,16 +58,26 @@ If `options.editorconfig` is `true` and an [`.editorconfig` file](http://editorc
Use `prettier.resolveConfig.sync(filePath [, options])` if you'd like to use sync version.
-## `prettier.resolveConfigFile(filePath [, options])`
+## `prettier.resolveConfigFile([filePath])`
-`resolveConfigFile` can be used to find the path of the Prettier's configuration file will be used when resolving the config (i.e. when calling `resolveConfig`). A promise is returned which will resolve to:
+`resolveConfigFile` can be used to find the path of the Prettier configuration file that will be used when resolving the config (i.e. when calling `resolveConfig`). A promise is returned which will resolve to:
- The path of the configuration file.
- `null`, if no file was found.
The promise will be rejected if there was an error parsing the configuration file.
-If `options.useCache` is `false`, all caching will be bypassed.
+The search starts at `process.cwd()`, or at `filePath` if provided. Please see the [cosmiconfig docs](https://github.com/davidtheclark/cosmiconfig#explorersearch) for details on how the resolving works.
+
+```js
+prettier.resolveConfigFile().then(filePath => {
+ prettier.resolveConfig(filePath).then(options => {
+ const formatted = prettier.format(text, options);
+ });
+});
+```
+
+Use `prettier.resolveConfigFile.sync([filePath])` if you'd like to use sync version.
## `prettier.clearConfigCache()`
@@ -84,10 +94,14 @@ As you repeatedly call `resolveConfig`, the file system structure will be cached
}
```
+The promise will be rejected if the type of `filePath` is not `string`.
+
Setting `options.ignorePath` (`string`) and `options.withNodeModules` (`boolean`) influence the value of `ignored` (`false` by default).
Providing [plugin](plugins.md) paths in `options.plugins` (`string[]`) helps extract `inferredParser` for files that are not supported by Prettier core.
+When setting `options.resolveConfig` (`boolean`, default `false`), Prettier will resolve the configuration for the given `filePath`. This is useful, for example, when the `inferredParser` might be overridden for a subset of files.
+
Use `prettier.getFileInfo.sync(filePath [, options])` if you'd like to use sync version.
## `prettier.getSupportInfo([version])`
diff --git a/docs/cli.md b/docs/cli.md
index 5dab730fc527..d1ef8bae0cac 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -17,7 +17,7 @@ In practice, this may look something like:
prettier --single-quote --trailing-comma es5 --write "{app,__{tests,mocks}__}/**/*.js"
```
-Don't forget the quotes around the globs! The quotes make sure that Prettier expands the globs rather than your shell, for cross-platform usage. The [glob syntax from the glob module](https://github.com/isaacs/node-glob/blob/master/README.md#glob-primer) is used.
+Don't forget the quotes around the globs! The quotes make sure that Prettier expands the globs rather than your shell, for cross-platform usage. The [glob syntax from the `fast-glob` module](https://github.com/mrmlnc/fast-glob/blob/master/README.md#pattern-syntax) is used.
Prettier CLI will ignore files located in `node_modules` directory. To opt-out from this behavior use `--with-node-modules` flag.
diff --git a/docs/configuration.md b/docs/configuration.md
index 14cbbe67adca..b28f61c90b12 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -3,12 +3,12 @@ id: configuration
title: Configuration File
---
-Prettier uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration file support. This means you can configure prettier via:
+Prettier uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration file support. This means you can configure prettier via (in order of precedence):
-- A `.prettierrc` file, written in YAML or JSON, with optional extensions: `.yaml/.yml/.json`.
-- A `.prettierrc.toml` file, written in TOML (the `.toml` extension is _required_).
-- A `prettier.config.js` or `.prettierrc.js` file that exports an object.
- A `"prettier"` key in your `package.json` file.
+- A `.prettierrc` file, written in JSON or YAML, with optional extensions: `.json/.yaml/.yml` (without extension takes precedence).
+- A `.prettierrc.js` or `prettier.config.js` file that exports an object.
+- A `.prettierrc.toml` file, written in TOML (the `.toml` extension is _required_).
The configuration file will be resolved starting from the location of the file being formatted, and searching up the file tree until a config file is (or isn't) found.
@@ -61,7 +61,9 @@ singleQuote = true
## Configuration Overrides
-Prettier borrows eslint's [override format](http://eslint.org/docs/user-guide/configuring#example-configuration). This allows you to apply configuration to specific files.
+Overrides let you have different configuration for certain file extensions, folders and specific files.
+
+Prettier borrows ESLint’s [override format](http://eslint.org/docs/user-guide/configuring#example-configuration).
JSON:
@@ -74,6 +76,12 @@ JSON:
"options": {
"semi": true
}
+ },
+ {
+ "files": ["*.html", "legacy/**/*.js"],
+ "options": {
+ "tabWidth": 4
+ }
}
]
}
@@ -87,6 +95,11 @@ overrides:
- files: "*.test.js"
options:
semi: true
+ - files:
+ - "*.html"
+ - "legacy/**/*.js"
+ options:
+ tabWidth: 4
```
`files` is required for each override, and may be a string or array of strings. `excludeFiles` may be optionally provided to exclude files for a given rule, and may also be a string or array of strings.
diff --git a/docs/integrating-with-linters.md b/docs/integrating-with-linters.md
index c2a92330adc1..57fa98f72a63 100644
--- a/docs/integrating-with-linters.md
+++ b/docs/integrating-with-linters.md
@@ -9,13 +9,13 @@ This allows you to use Prettier for code formatting concerns, while letting your
Whatever linting tool you wish to integrate with, the steps are broadly similar.
First disable any existing formatting rules in your linter that may conflict with how Prettier wishes to format your code. Then you can either add an extension to your linting tool to format your file with Prettier - so that you only need a single command for format a file, or run your linter then Prettier as separate steps.
-All these instructions assume you have already installed `prettier` in your `devDependencies`.
+All these instructions assume you have already installed `prettier` in your [`devDependencies`].
## ESLint
### Disable formatting rules
-[`eslint-config-prettier`](https://github.com/prettier/eslint-config-prettier) is a config that disables rules that conflict with Prettier. Add it to your `devDependencies`, then extend from it within your `.eslintrc` configuration. Make sure to put it last in the `extends` array, so it gets the chance to override other configs.
+[`eslint-config-prettier`](https://github.com/prettier/eslint-config-prettier) is a config that disables rules that conflict with Prettier. Add it to your [`devDependencies`], then extend from it within your `.eslintrc` configuration. Make sure to put it last in the `extends` array, so it gets the chance to override other configs.
```bash
yarn add --dev eslint-config-prettier
@@ -31,7 +31,7 @@ Then in `.eslintrc.json`:
### Use ESLint to run Prettier
-[`eslint-plugin-prettier`](https://github.com/prettier/eslint-plugin-prettier) is a plugin that adds a rule that formats content using Prettier. Add it to your `devDependencies`, then enable the plugin and rule.
+[`eslint-plugin-prettier`](https://github.com/prettier/eslint-plugin-prettier) is a plugin that adds a rule that formats content using Prettier. Add it to your [`devDependencies`], then enable the plugin and rule.
```bash
yarn add --dev eslint-plugin-prettier
@@ -68,7 +68,7 @@ Then in `.eslintrc.json`:
### Disable formatting rules
-[`tslint-config-prettier`](https://github.com/alexjoverm/tslint-config-prettier) is a config that disables rules that conflict with Prettier. Add it to your `devDependencies`, then extend from it within your `tslint.json` configuration. Make sure to put it last in the `extends` array, so it gets the chance to override other configs.
+[`tslint-config-prettier`](https://github.com/alexjoverm/tslint-config-prettier) is a config that disables rules that conflict with Prettier. Add it to your [`devDependencies`], then extend from it within your `tslint.json` configuration. Make sure to put it last in the `extends` array, so it gets the chance to override other configs.
```bash
yarn add --dev tslint-config-prettier
@@ -84,7 +84,7 @@ Then in `tslint.json`:
### Use TSLint to run Prettier
-[`tslint-plugin-prettier`](https://github.com/ikatyang/tslint-plugin-prettier) is a plugin that adds a rule that formats content using Prettier. Add it to your `devDependencies`, then enable the plugin and rule.
+[`tslint-plugin-prettier`](https://github.com/ikatyang/tslint-plugin-prettier) is a plugin that adds a rule that formats content using Prettier. Add it to your [`devDependencies`], then enable the plugin and rule.
```bash
yarn add --dev tslint-plugin-prettier
@@ -140,7 +140,7 @@ Then in `.stylelintrc`:
### Use Stylelint to run Prettier
-[`stylelint-prettier`](https://github.com/prettier/stylelint-prettier) is a plugin that adds a rule that formats content using Prettier. Add it to your `devDependencies`, then enable the plugin and rule.
+[`stylelint-prettier`](https://github.com/prettier/stylelint-prettier) is a plugin that adds a rule that formats content using Prettier. Add it to your [`devDependencies`], then enable the plugin and rule.
```bash
yarn add --dev stylelint-prettier
@@ -172,3 +172,5 @@ Then in `.stylelintrc`:
"extends": ["stylelint-prettier/recommended"]
}
```
+
+[`devdependencies`]: https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file
diff --git a/docs/option-philosophy.md b/docs/option-philosophy.md
index d3bd181b410f..f56fdda7afd2 100644
--- a/docs/option-philosophy.md
+++ b/docs/option-philosophy.md
@@ -3,6 +3,10 @@ id: option-philosophy
title: Option Philosophy
---
+> Prettier has a few options because of history. **But we don’t want more of them.**
+>
+> Read on to learn more.
+
Prettier is not a kitchen-sink code formatter that attempts to print your code in any way you wish. It is _opinionated._ Quoting the [Why Prettier?](why-prettier.md) page:
> By far the biggest reason for adopting Prettier is to stop all the on-going debates over styles.
@@ -11,21 +15,33 @@ The more options Prettier has, the further from the above goal it gets. **The de
The issue about [resisting adding configuration](https://github.com/prettier/prettier/issues/40) has more 👍s than any option request issue.
-So why does Prettier have options at all?
+So why are there any options at all?
+
+- A few were added during Prettier’s infancy to make it take off at all. 🚀
+- A couple were added after “great demand.” 🤔
+- Some were added for compatibility reasons. 👍
+
+What we’ve learned during the years is that it’s really hard to measure demand. Prettier has grown _a lot_ in usage. What was “great demand” back in the day is not as much today. How many is many? What about all silent users?
+
+It’s so easy to add “just one more“ option. But where do we stop? When is one too many? There will always be a “top issue” in the issue tracker. Even if we add just that one final option.
+
+The downside of options is that they open up for debate within teams. Which options should we use? Why? Did we make the right choices?
+
+Every option also makes it much harder to say no to new ones. If _those_ options exist, why can’t this one?
+
+We’ve had several users open up option requests only to close them themselves a couple of months later. They had realized that they don’t care at all about that little syntax choice they used to feel so strongly about. Examples: [#3101](https://github.com/prettier/prettier/issues/3101#issuecomment-500927917) and [#5501](https://github.com/prettier/prettier/issues/5501#issuecomment-487025417).
-Well, had Prettier been created around the same time as JavaScript itself was born it could have made choices that the community would have picked up (which is the case for [elm-format](https://github.com/avh4/elm-format/)). But JavaScript is far older than Prettier so the community has had time to start their holy wars about tabs vs spaces, single vs double quotes, indentation levels, trailing commas and semicolons, so Prettier more or less has to support those.
+All of this makes the topic of options in Prettier very difficult. And mentally tiring for maintainers. What do people want? What do people _really_ want in 6 months? Are we spending time and energy on the right things?
-Then there's a bunch of interesting cases.
+Some options are easier to motivate:
-- `--trailing-comma es5` was added to make it easier to use trailing commas in most environments without having to transpile (trailing function commas were added in ES2017).
+- `--trailing-comma es5` lets you use trailing commas in most environments without having to transpile (trailing function commas were added in ES2017).
- `--prose-wrap` is important to support all quirky markdown renderers in the wild.
- `--html-whitespace-sensitivity` is needed due to the unfortunate whitespace rules of HTML.
- `--end-of-line` makes it easier for teams to keep CRLFs out of their git repositories.
-- `--arrow-parens` was added after – at the time – [huge demand](https://github.com/prettier/prettier/issues/812). Prettier has to strike a balance between ideal goals and listening to the community.
-- `--jsx-single-quote` was also added after [great demand](https://github.com/prettier/prettier/issues/1080), but after more consideration. It took quite some time to figure out the right approach.
-- `--jsx-bracket-same-line` was needed for a big company with a huge code base (Facebook), which backed the project when it got started, to be able to [adopt Prettier at all](https://github.com/prettier/prettier/pull/661#issuecomment-295770645).
+- `--quote-props` is important for advanced usage of the Google Closure Compiler.
-Finally, perhaps the most interesting of them all is `--bracket-spacing`.
-The truth is that not even [Prettier's creator knows exactly why it exists](https://github.com/prettier/prettier/issues/715#issuecomment-281096495). It was added super early on without much thought. It now serves as an example of the types of options we should avoid.
+But others are harder to motivate in hindsight, and usually end up with bike shedding. `--arrow-parens`,
+`--jsx-single-quote`, `--jsx-bracket-same-line` and `--no-bracket-spacing` are not the type of options we want more of. They exist (and are difficult to remove now), but should not motivate adding more options like them.
-Remember, it is easy to _add_ features to a program, but hard to remove them.
+Feel free to open issues! Prettier isn’t perfect. Many times things can be improved without adding options. But if the issue _does_ seem to need a new option, we’ll generally keep it open, to let people 👍 it and add comments.
diff --git a/docs/options.md b/docs/options.md
index 46450310fb81..00f647107da2 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -307,6 +307,21 @@ Valid options:
| ------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| `"css"` | --html-whitespace-sensitivity | htmlWhitespaceSensitivity: "" |
+## Vue files script and style tags indentation
+
+_First available in v1.19.0_
+
+Whether or not to indent the code inside `
+
+
+
+=====================================output=====================================
+
+
+
+================================================================================
+`;
+
+exports[`basic-handlebars.hbs 2`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 80
+singleQuote: true
+ | printWidth
+=====================================input======================================
+
+
+
+
+=====================================output=====================================
+
+
+
+================================================================================
+`;
+
+exports[`component.hbs 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+
+{{@greeting}}, {{@name}}!
+
+
+{{#if isAtWork}}
+ Ship that code!
+{{else if isReading}}
+ You can finish War and Peace eventually...
+{{else}}
+ Go to bed!
+{{/if}}
+
+
+
+{{#if a}}
+ A
+{{else}}
+ B
+{{/if}}
+
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ hello
+ {{#if f}}
+ g
+ {{/if}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else if e}}
+ f
+{{else if g}}
+ h
+{{else}}
+ j
+{{/if}}
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+{{#if a}}
+ b
+{{else}}
+ {{#each c as |d|}}
+ e
+ {{/each}}
+{{/if}}
+
+{{#if a}}
+ {{#if b}}
+ ab
+ {{else if c}}
+ ac
+ {{/if}}
+{{/if}}
+
+{{#if a}}
+ a
+
b
+ c
+{{else}}
+ {{#if c}}
+ a
+ b
+
c
+ {{/if}}
+
a
+ b
+ c
+{{/if}}
+
+=====================================output=====================================
+
+ {{#if isAtWork}}
+ Ship that code!
+ {{else if isReading}}
+ You can finish War and Peace eventually...
+ {{else}}
+ Go to bed!
+ {{/if}}
+
+
+
+ {{#if a}}
+ A
+ {{else}}
+ B
+ {{/if}}
+
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ hello
+ {{#if f}}
+ g
+ {{/if}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else if e}}
+ f
+{{else if g}}
+ h
+{{else}}
+ j
+{{/if}}
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+{{#if a}}
+ b
+{{else}}
+ {{#each c as |d|}}
+ e
+ {{/each}}
+{{/if}}
+
+{{#if a}}
+ {{#if b}}
+ ab
+ {{else if c}}
+ ac
+ {{/if}}
+{{/if}}
+
+{{#if a}}
+ a
+
+{{#if isAtWork}}
+ Ship that code!
+{{else if isReading}}
+ You can finish War and Peace eventually...
+{{else}}
+ Go to bed!
+{{/if}}
+
+
+
+{{#if a}}
+ A
+{{else}}
+ B
+{{/if}}
+
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ hello
+ {{#if f}}
+ g
+ {{/if}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else if e}}
+ f
+{{else if g}}
+ h
+{{else}}
+ j
+{{/if}}
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+{{#if a}}
+ b
+{{else}}
+ {{#each c as |d|}}
+ e
+ {{/each}}
+{{/if}}
+
+{{#if a}}
+ {{#if b}}
+ ab
+ {{else if c}}
+ ac
+ {{/if}}
+{{/if}}
+
+{{#if a}}
+ a
+
b
+ c
+{{else}}
+ {{#if c}}
+ a
+ b
+
c
+ {{/if}}
+
a
+ b
+ c
+{{/if}}
+
+=====================================output=====================================
+
+ {{#if isAtWork}}
+ Ship that code!
+ {{else if isReading}}
+ You can finish War and Peace eventually...
+ {{else}}
+ Go to bed!
+ {{/if}}
+
+
+
+ {{#if a}}
+ A
+ {{else}}
+ B
+ {{/if}}
+
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else}}
+ hello
+ {{#if f}}
+ g
+ {{/if}}
+ e
+{{/if}}
+
+{{#if a}}
+ b
+{{else if c}}
+ d
+{{else if e}}
+ f
+{{else if g}}
+ h
+{{else}}
+ j
+{{/if}}
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+
+ {{#if a}}
+ b
+ {{else if c}}
+ d
+ {{else}}
+ e
+ {{/if}}
+
+
+
+{{#if a}}
+ b
+{{else}}
+ {{#each c as |d|}}
+ e
+ {{/each}}
+{{/if}}
+
+{{#if a}}
+ {{#if b}}
+ ab
+ {{else if c}}
+ ac
+ {{/if}}
+{{/if}}
+
+{{#if a}}
+ a
+
{{! This comment will not be in the output }}
{{!-- This comment as }} and will not be in the output --}}
diff --git a/tests/handlebars/jsfmt.spec.js b/tests/handlebars-comment/jsfmt.spec.js
similarity index 100%
rename from tests/handlebars/jsfmt.spec.js
rename to tests/handlebars-comment/jsfmt.spec.js
diff --git a/tests/handlebars-concat-statement/__snapshots__/jsfmt.spec.js.snap b/tests/handlebars-concat-statement/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..4be7aaf87d14
--- /dev/null
+++ b/tests/handlebars-concat-statement/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,124 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`concat-statement.hbs 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+
+ We are a cooperative, one of the few seed companies so organized
+ in the United States. Because we do not have an individual owner or beneficiary,
+ profit is not our primary goal. Consumers own 60% of the cooperative and worker
+ members 40%. Consumer and worker members share proportionately in the cooperative’s
+ profits through our annual patronage dividends.
+
+
+
+ We are a cooperative
+
+ , one of the few seed companies so organized
+ in the United States. Because we do not have an individual owner or beneficiary,
+ profit is not our primary goal. Consumers own 60% of the cooperative and worker
+ members 40%. Consumer and worker members share proportionately in the cooperative’s
+ profits through our annual patronage dividends.
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce cursus massa vel augue
+vestibulum facilisis in porta turpis. Ut faucibus lectus sit amet urna consectetur dignissim.
+Sam vitae neque quis ex dapibus faucibus at sed ligula. Nulla sit amet aliquet nibh.
+Vestibulum at congue mi. Suspendisse vitae odio vitae massa hendrerit mattis sed eget dui.
+Sed eu scelerisque neque. Donec maximus rhoncus pellentesque. Aenean purus turpis, vehicula
+euismod ante vel, ultricies eleifend dui. Class aptent taciti sociosqu ad litora torquent per
+conubia nostra, per inceptos himenaeos. Donec in ornare velit.
+
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce cursus massa vel augue
+vestibulum facilisis in porta turpis. Ut faucibus lectus sit amet urna consectetur dignissim.
+Sam vitae neque quis ex dapibus faucibus at sed ligula. Nulla sit amet aliquet nibh.
+Vestibulum at congue mi. Suspendisse vitae odio vitae massa hendrerit mattis sed eget dui.
+Sed eu scelerisque neque. Donec maximus rhoncus pellentesque. Aenean purus turpis, vehicula
+euismod ante vel, ultricies eleifend dui. Class aptent taciti sociosqu ad litora torquent per
+conubia nostra, per inceptos himenaeos. Donec in ornare velit.
+
+=====================================output=====================================
+{{! TO FIX }}
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce cursus massa vel augue
+vestibulum facilisis in porta turpis. Ut faucibus lectus sit amet urna consectetur dignissim.
+Sam vitae neque quis ex dapibus faucibus at sed ligula. Nulla sit amet aliquet nibh.
+Vestibulum at congue mi. Suspendisse vitae odio vitae massa hendrerit mattis sed eget dui.
+Sed eu scelerisque neque. Donec
+
+ maximus
+
+ rhoncus pellentesque. Aenean purus turpis, vehicula
+euismod ante vel, ultricies eleifend dui. Class aptent taciti sociosqu ad litora torquent per
+conubia nostra, per inceptos himenaeos. Donec in ornare velit.
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce cursus massa vel augue
+vestibulum facilisis in porta turpis. Ut faucibus lectus sit amet urna consectetur dignissim.
+Sam vitae neque quis ex dapibus faucibus at sed ligula. Nulla sit amet aliquet nibh.
+Vestibulum at congue mi. Suspendisse vitae odio vitae massa hendrerit mattis sed eget dui.
+Sed eu scelerisque neque. Donec
+
+
+ maximus
+
+
+ rhoncus pellentesque. Aenean purus turpis, vehicula
+euismod ante vel, ultricies eleifend dui. Class aptent taciti sociosqu ad litora torquent per
+conubia nostra, per inceptos himenaeos. Donec in ornare velit.
+
+================================================================================
+`;
+
+exports[`non-breaking-whitespace.hbs 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 40
+ | printWidth
+=====================================input======================================
+
+Nihil aut odit omnis. Quam maxime est molestiae. Maxime dolorem dolores voluptas quaerat ut qui sunt vitae error.
+
+Nihil aut odit omnis. Quam maxime est molestiae. Maxime dolorem dolores voluptas quaerat ut qui sunt vitae error.
+
+Prix : 32 €
+
+=====================================output=====================================
+
+
+ Nihil aut odit omnis. Quam maxime est molestiae. Maxime dolorem dolores voluptas quaerat ut qui sunt vitae error.
+
+
+
+ Nihil aut odit omnis. Quam maxime est molestiae. Maxime dolorem dolores voluptas quaerat ut qui sunt vitae error.
+
+
+
+ Prix : 32 €
+
+================================================================================
+`;
+
+exports[`punctuation.hbs 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 40
+ | printWidth
+=====================================input======================================
+This is your name: {{name}}.
+This is your name: {{name}} (employee)
+This is your name: {{name}} ({{role}})
+
+=====================================output=====================================
+
+ This is your name: {{name}}.
+
+
+ This is your name: {{name}} (employee)
+
+
+ This is your name: {{name}} ({{role}})
+
+================================================================================
+`;
+
+exports[`surrounding-linebreak.hbs 1`] = `
+====================================options=====================================
+parsers: ["glimmer"]
+printWidth: 40
+ | printWidth
+=====================================input======================================
+123
+
+123
+123
+
+
+123
+
+
+
;
diff --git a/tests/handlebars-whitespace/boss.hbs b/tests/handlebars-whitespace/boss.hbs
new file mode 100644
index 000000000000..1e15a8a9c5e1
--- /dev/null
+++ b/tests/handlebars-whitespace/boss.hbs
@@ -0,0 +1,15 @@
+
Hi {{firstName}} {{lastName}} , welcome!
+{{#component propA}}
+ for {{propB}} do {{propC}} f
+{{/component}}
+{{#component propA}}
+ for {{propB}} namedo {{propC}} f
+{{/component}}
+{{propA}} {{propB}}
+{{propC}}{{propD}}
+{{propE}} {{propF}}
+{{propG}}{{propH}}
+
+
+
+hey
diff --git a/tests/glimmer/curly.hbs b/tests/handlebars-whitespace/curly.hbs
similarity index 100%
rename from tests/glimmer/curly.hbs
rename to tests/handlebars-whitespace/curly.hbs
diff --git a/tests/handlebars-whitespace/display-inline-block.hbs b/tests/handlebars-whitespace/display-inline-block.hbs
new file mode 100644
index 000000000000..abb068528c14
--- /dev/null
+++ b/tests/handlebars-whitespace/display-inline-block.hbs
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/handlebars-whitespace/display-none.hbs b/tests/handlebars-whitespace/display-none.hbs
new file mode 100644
index 000000000000..0570c11ee3ad
--- /dev/null
+++ b/tests/handlebars-whitespace/display-none.hbs
@@ -0,0 +1,2 @@
+{{!-- TO FIX --}}
+My tITlE
diff --git a/tests/handlebars-whitespace/fill.hbs b/tests/handlebars-whitespace/fill.hbs
new file mode 100644
index 000000000000..3a475a4263da
--- /dev/null
+++ b/tests/handlebars-whitespace/fill.hbs
@@ -0,0 +1,11 @@
+
+ We are a cooperative, one of the few seed companies so organized
+ in the United States. Because we do not have an individual owner or beneficiary,
+ profit is not our primary goal. Consumers own 60% of the cooperative and worker
+ members 40%. Consumer and worker members share proportionately in the cooperative’s
+ profits through our annual patronage dividends.
+
diff --git a/tests/handlebars-whitespace/inline-element.hbs b/tests/handlebars-whitespace/inline-element.hbs
new file mode 100644
index 000000000000..749afd13cdff
--- /dev/null
+++ b/tests/handlebars-whitespace/inline-element.hbs
@@ -0,0 +1,16 @@
+{{!-- TO FIX --}}
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce cursus massa vel augue
+vestibulum facilisis in porta turpis. Ut faucibus lectus sit amet urna consectetur dignissim.
+Sam vitae neque quis ex dapibus faucibus at sed ligula. Nulla sit amet aliquet nibh.
+Vestibulum at congue mi. Suspendisse vitae odio vitae massa hendrerit mattis sed eget dui.
+Sed eu scelerisque neque. Donec maximus rhoncus pellentesque. Aenean purus turpis, vehicula
+euismod ante vel, ultricies eleifend dui. Class aptent taciti sociosqu ad litora torquent per
+conubia nostra, per inceptos himenaeos. Donec in ornare velit.
+
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce cursus massa vel augue
+vestibulum facilisis in porta turpis. Ut faucibus lectus sit amet urna consectetur dignissim.
+Sam vitae neque quis ex dapibus faucibus at sed ligula. Nulla sit amet aliquet nibh.
+Vestibulum at congue mi. Suspendisse vitae odio vitae massa hendrerit mattis sed eget dui.
+Sed eu scelerisque neque. Donec maximus rhoncus pellentesque. Aenean purus turpis, vehicula
+euismod ante vel, ultricies eleifend dui. Class aptent taciti sociosqu ad litora torquent per
+conubia nostra, per inceptos himenaeos. Donec in ornare velit.
diff --git a/tests/handlebars-whitespace/jsfmt.spec.js b/tests/handlebars-whitespace/jsfmt.spec.js
new file mode 100644
index 000000000000..36123c9a9e0f
--- /dev/null
+++ b/tests/handlebars-whitespace/jsfmt.spec.js
@@ -0,0 +1 @@
+run_spec(__dirname, ["glimmer"], { printWidth: 40 });
diff --git a/tests/handlebars-whitespace/non-breaking-whitespace.hbs b/tests/handlebars-whitespace/non-breaking-whitespace.hbs
new file mode 100644
index 000000000000..55a8b9477611
--- /dev/null
+++ b/tests/handlebars-whitespace/non-breaking-whitespace.hbs
@@ -0,0 +1,6 @@
+
+Nihil aut odit omnis. Quam maxime est molestiae. Maxime dolorem dolores voluptas quaerat ut qui sunt vitae error.
+
+Nihil aut odit omnis. Quam maxime est molestiae. Maxime dolorem dolores voluptas quaerat ut qui sunt vitae error.
+
+Prix : 32 €
diff --git a/tests/handlebars-whitespace/punctuation.hbs b/tests/handlebars-whitespace/punctuation.hbs
new file mode 100644
index 000000000000..762851bd11c5
--- /dev/null
+++ b/tests/handlebars-whitespace/punctuation.hbs
@@ -0,0 +1,3 @@
+This is your name: {{name}}.
+This is your name: {{name}} (employee)
+This is your name: {{name}} ({{role}})
diff --git a/tests/handlebars-whitespace/surrounding-linebreak.hbs b/tests/handlebars-whitespace/surrounding-linebreak.hbs
new file mode 100644
index 000000000000..06862ebaa584
--- /dev/null
+++ b/tests/handlebars-whitespace/surrounding-linebreak.hbs
@@ -0,0 +1,17 @@
+123
+
+123
+123
+
+
+123
+
+
+
123
+
+123
+
123
+
+
+123
+
diff --git a/tests/handlebars-whitespace/table.hbs b/tests/handlebars-whitespace/table.hbs
new file mode 100644
index 000000000000..c161476daa7e
--- /dev/null
+++ b/tests/handlebars-whitespace/table.hbs
@@ -0,0 +1,20 @@
+
{{title}}
+