website/blog/2019-11-09-1.19.0.md
This release adds the long awaited --vue-indent-script-and-style option, support for TypeScript 3.7 and some cutting edge JavaScript syntax. Not to mention a whole bunch of bug fixes and improvements!
--vue-indent-script-and-style (#6157 by @kamilic)The new --vue-indent-script-and-style option controls whether or not to indent the code inside <script> and <style> tags in Vue files. Some people (like the creator of Vue) don’t indent to save an indentation level, but this might break code folding in your editor. This closes our most commented issue so far, and should improve lots of Vue coders’ editing experience!
Prettier 1.19 adds support for the features of the upcoming TypeScript 3.7 that introduce new syntax:
(Note: A dependency upgrade for TypeScript 3.7 led to dropping Node.js 6 support for direct installation from GitHub. Prettier installed from npm stays compatible with Node.js 4.)
// Input
const longChain = obj?.a?.b?.c?.d?.e?.f?.g;
const longChainCallExpression = obj.a?.(a,b,c).b?.(a,b,c).c?.(a,b,c).d?.(a,b,c).e?.(a,b,c).f?.(a,b,c)
// Prettier 1.19
const longChain = obj?.a?.b?.c?.d?.e?.f?.g;
const longChainCallExpression = obj
.a?.(a, b, c)
.b?.(a, b, c)
.c?.(a, b, c)
.d?.(a, b, c)
.e?.(a, b, c)
.f?.(a, b, c);
// Input
const cond = null;
const result = cond??'a';
const longChain = cond??cond??cond??'b';
// Prettier 1.19
const cond = null;
const result = cond ?? "a";
const longChain = cond ?? cond ?? cond ?? "b";
// Input
function assertsString(x: any): asserts x {console.assert(typeof x === 'string');}
function assertsStringWithGuard(x: any): asserts x is string {console.assert(typeof x === 'string');}
// Prettier 1.19
function assertsString(x: any): asserts x {
console.assert(typeof x === "string");
}
function assertsStringWithGuard(x: any): asserts x is string {
console.assert(typeof x === "string");
}
declare Modifier on Class Fields// Input
class B {p: number;}
class C extends B {declare p: 256 | 1000;}
// Prettier 1.19
class B {
p: number;
}
class C extends B {
declare p: 256 | 1000;
}
// Input
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`.
// Prettier 1.18
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
// Prettier 1.19
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\`.
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:
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 (#5769, #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.
Try it out and feel free to provide feedback!
<!-- prettier-ignore -->// Input
eventStore.update(id, _.flow(updater, incrementVersion));
// Prettier 1.18
eventStore.update(
id,
_.flow(
updater,
incrementVersion
)
);
// Prettier 1.19
eventStore.update(id, _.flow(updater, incrementVersion));
We updated the Babel parser to the latest version and got an awesome feature for free. Prettier is now able to format your code even if it is invalid in some cases, which should make your coding experience smoother. This will get better over time as Babel improves their error recovery parsing mode. Read more in the Babel 7.7.0 blog post!
<!-- prettier-ignore -->// Input
let a = {
__proto__ : x,
__proto__ : y
}
let a = 2
// Prettier 1.18
SyntaxError: Redefinition of __proto__ property (3:3)
1 | let a = {
2 | __proto__ : x,
> 3 | __proto__ : y
| ^
4 | }
5 | let a = 2
// Prettier 1.19
let a = {
__proto__: x,
__proto__: y
};
let a = 2;
This is still broken if the key is a complex expression, but it has been fixed in these cases:
<!-- prettier-ignore -->// Input
class Foo {
[bar]?: number;
protected [s]?() {}
}
// Prettier 1.18
class Foo {
[bar]: number;
protected [s?]() {};
}
// Prettier 1.19
class Foo {
[bar]?: number;
protected [s]?() {}
}
// Input
const comp = (
<Foo<number>
// This comment goes missing
value={4}
>
Test
</Foo>
);
// Prettier 1.18
const comp = <Foo<number> value={4}>Test</Foo>;
// Prettier 1.19
const comp = (
<Foo<number>
// This comment goes missing
value={4}
>
Test
</Foo>
);
// in JSX texts (#6289 by @duailibe)This version updates the TypeScript parser to correctly handle JSX text with double slashes (//). In previous versions, this would cause Prettier to crash.
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.
<!-- prettier-ignore -->// Input
type FooBar<T> = { [P in keyof T]: T[P] extends Something ? Something<T[P]> : T[P] }
// Prettier 1.18
type FooBar<T> = {
[P in keyof T]: T[P] extends Something ? Something<T[P]> : T[P]
};
// Prettier 1.19
type FooBar<T> = {
[P in keyof T]: T[P] extends Something ? Something<T[P]> : T[P];
};
// Input
const fooooooooooooooo: SomeThing<boolean> = looooooooooooooooooooooooooooooongNameFunc();
// Prettier 1.18
const fooooooooooooooo: SomeThing<
boolean
> = looooooooooooooooooooooooooooooongNameFunc();
// Prettier 1.19
const fooooooooooooooo: SomeThing<boolean> = looooooooooooooooooooooooooooooongNameFunc();
// 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 1.18
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 1.19
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"];
// Input
(<a />).toString();
// Prettier 1.18
<a />.toString():
// Prettier 1.19
(<a />).toString();
Attempting to format Prettier’s output again used to result in a syntax error.
<!-- prettier-ignore -->// Input
export class User {
id: number = 2;
[key: string]: any
}
// Prettier 1.18
export class User {
id: number = 2
[key: string]: any
}
// Prettier 1.19
export class User {
id: number = 2;
[key: string]: any
}
as type expressions (#6471 by @mattleff)Previously, when Prettier formatted a call expression containing an as type expression or a type assertion, it would break the line. Now, Prettier uses the expression contained by the as type or type assertion to determine line breaks.
// Input
const bar = [1,2,3].reduce((carry, value) => {
return [...carry, value];
}, ([] as unknown) as number[]);
// Prettier 1.18
const bar = [1, 2, 3].reduce(
(carry, value) => {
return [...carry, value];
},
([] as unknown) as number[]
);
// Prettier 1.19
const bar = [1,2,3].reduce((carry, value) => {
return [...carry, value];
}, ([] as unknown) as number[]);
// 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]
]
// Prettier 1.18
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
]
];
// Prettier 1.19
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
]
];
useEffect (#6270 by @sosukesuzuki)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.
<!-- prettier-ignore -->// Input
useEffect(
() => {
console.log("some code", props.foo);
},
// eslint-disable-line react-hooks/exhaustive-deps
[]
);
// Prettier 1.18
useEffect(() => {
console.log("some code", props.foo);
}, // eslint-disable-line react-hooks/exhaustive-deps
[]);
// Prettier 1.19
useEffect(
() => {
console.log("some code", props.foo);
},
// eslint-disable-line react-hooks/exhaustive-deps
[]
);
// Input
const foo = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (
| string
| undefined
)[];
// Prettier 1.18
const foo = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (
| string
| undefined)[];
// Prettier 1.19
const foo = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (
| string
| undefined
)[];
// Input
enum E of string {
A = "a", B = "b"
}
// Prettier 1.19
enum E of string {
A = "a",
B = "b",
}
FunctionTypeAnnotation nested in ObjectTypeAnnotation (#6717 by @sosukesuzuki)This is a workaround for a bug in the Flow parser. Without the parentheses, the parser throws an error.
// Input
const example1 = (): { p: (string => string) } => (0: any);
// Prettier 1.18
const example1 = (): { p: string => string } => (0: any);
// Prettier 1.19
const example1 = (): ({ p: string => string }) => (0: any);
This should format your new Map and Jest test.each calls more nicely.
// Input
test.each([
{ a: "1", b: 1 },
{ a: "2", b: 2 },
{ a: "3", b: 3 }
])("test", ({ a, b }) => {
expect(Number(a)).toBe(b);
});
[[0, 1, 2], [0, 1, 2]];
new Map([
[A, B],
[C, D],
[E, F],
[G, H],
[I, J],
[K, L],
[M, N]
]);
// Prettier 1.18
test.each([{ a: "1", b: 1 }, { a: "2", b: 2 }, { a: "3", b: 3 }])(
"test",
({ a, b }) => {
expect(Number(a)).toBe(b);
}
);
[[0, 1, 2], [0, 1, 2]]
new Map([[A, B], [C, D], [E, F], [G, H], [I, J], [K, L], [M, N]]);
// Prettier 1.19
test.each([
{ a: "1", b: 1 },
{ a: "2", b: 2 },
{ a: "3", b: 3 }
])("test", ({ a, b }) => {
expect(Number(a)).toBe(b);
});
[
[0, 1, 2],
[0, 1, 2]
];
new Map([
[A, B],
[C, D],
[E, F],
[G, H],
[I, J],
[K, L],
[M, N]
]);
?? precedence to match stage 3 proposal (#6404 by @vjeux, #6863 by @jridgewell)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.
// Input
(foo ?? bar) || baz;
(foo || bar) ?? baz;
// Prettier 1.18
foo ?? bar || baz;
foo || bar ?? baz;
// Prettier 1.19
(foo ?? bar) || baz;
(foo || bar) ?? baz;
Please note that since we have updated our parsers with versions that support this spec update, code without the parentheses will throw a parse error.
// Input
foo && (bar && baz);
foo || (bar || baz);
foo ?? (bar ?? baz);
// Prettier 1.18
foo && (bar && baz);
foo || (bar || baz);
foo ?? (bar ?? baz);
// Prettier 1.19
foo && bar && baz;
foo || bar || baz;
foo ?? bar ?? baz;
new call (#6412 by @bakkot)// Input
var a = new (x().y)();
var a = new (x().y.z)();
var a = new (x().y().z)();
// Prettier 1.18
var a = new (x()).y();
var a = new (x()).y.z();
var a = new (x().y()).z();
// Prettier 1.19
var a = new (x().y)();
var a = new (x().y.z)();
var a = new (x().y().z)();
// Input
!(
/* foo */
foo
);
!(
foo // foo
);
// Prettier 1.18
!/* foo */
foo;
!foo; // foo
// Prettier 1.19
!(/* foo */ foo);
!(
foo // foo
);
// Input
foo //comment
`
`;
// Prettier 1.18
foo` // comment
`;
// Prettier 1.19
foo // comment
`
`;
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 for details.
<!-- prettier-ignore -->// Input
foo(
({
a,
b
}) => {}
);
// Prettier 1.18
foo(({ a,
b }) => {});
// Prettier 1.19
foo(
({
a,
b
}) => {}
);
// Input
class Class {
method(
@decorator
{ foo }
) {}
}
// Prettier 1.18
class Class {
method(@decorator
{
foo
}) {}
}
// Prettier 1.19
class Class {
method(
@decorator
{ foo }
) {}
}
// Input
const f = ({}: MyVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongType) => {};
function g({}: Foo) {}
// Prettier 1.18
const f = ({
,
}: MyVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongType) => {};
function g({ }: Foo) {}
// Prettier 1.19
const f = ({}: MyVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongType) => {};
function g({}: Foo) {}
// Input
(
aaaaaaaaaaaaaaaaaaaaaaaaa &&
bbbbbbbbbbbbbbbbbbbbbbbbb &&
ccccccccccccccccccccccccc &&
ddddddddddddddddddddddddd &&
eeeeeeeeeeeeeeeeeeeeeeeee
)();
// Prettier 1.18
(aaaaaaaaaaaaaaaaaaaaaaaaa &&
bbbbbbbbbbbbbbbbbbbbbbbbb &&
ccccccccccccccccccccccccc &&
ddddddddddddddddddddddddd &&
eeeeeeeeeeeeeeeeeeeeeeeee)();
// Prettier 1.19
(
aaaaaaaaaaaaaaaaaaaaaaaaa &&
bbbbbbbbbbbbbbbbbbbbbbbbb &&
ccccccccccccccccccccccccc &&
ddddddddddddddddddddddddd &&
eeeeeeeeeeeeeeeeeeeeeeeee
)();
Now, Prettier formats named exports the same way as named imports.
<!-- prettier-ignore -->// Input
export { fooooooooooooooooooooooooooooooooooooooooooooooooo } from "fooooooooooooooooooooooooooooo";
// Prettier 1.18
export {
fooooooooooooooooooooooooooooooooooooooooooooooooo
} from "fooooooooooooooooooooooooooooo";
// Prettier 1.19
export { fooooooooooooooooooooooooooooooooooooooooooooooooo } from "fooooooooooooooooooooooooooooo";
// Input
return a
.b()
.c()
// Comment
?.d()
// Prettier 1.18
return a
.b()
.c()
?.// Comment
d();
// Prettier 1.19
return (
a
.b()
.c()
// Comment
?.d()
);
// Input
switch ($veryLongAndVeryVerboseVariableName && $anotherVeryLongAndVeryVerboseVariableName) {
}
switch ($longButSlightlyShorterVariableName && $anotherSlightlyShorterVariableName) {
}
// Prettier 1.18
switch (
$veryLongAndVeryVerboseVariableName &&
$anotherVeryLongAndVeryVerboseVariableName
) {
}
switch (
$longButSlightlyShorterVariableName && $anotherSlightlyShorterVariableName
) {
}
// Prettier 1.19
switch (
$veryLongAndVeryVerboseVariableName &&
$anotherVeryLongAndVeryVerboseVariableName
) {
}
switch (
$longButSlightlyShorterVariableName &&
$anotherSlightlyShorterVariableName
) {
}
// Input
function doSmth() {
%DebugPrint
(
foo )
}
// Prettier 1.18
SyntaxError: Unexpected token (2:13)
1 | function doSmth() {
> 2 | %DebugPrint
| ^
// Prettier 1.19
function doSmth() {
%DebugPrint(foo);
}
// 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 1.18
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 1.19
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;
}
}
// Input
const bigints = [200_000n, 0x0000_000An, 0b0111_1111n];
// Prettier 1.18
const bigints = [200000n, 0x0000000an, 0b01111111n];
// Prettier 1.19
const bigints = [200_000n, 0x0000_000an, 0b0111_1111n];
await expression nested in calls (#6856 by @thorn0)// Input
async function f() {
const admins = (await(db.select('*').from('admins').leftJoin('bla').where('id', 'in', [1,2,3,4]))).map(({id, name})=>({id, name}))
}
// Prettier 1.18
async function f() {
const admins = (await db
.select("*")
.from("admins")
.leftJoin("bla")
.where("id", "in", [1, 2, 3, 4])).map(({ id, name }) => ({ id, name }));
}
// Prettier 1.19
async function f() {
const admins = (
await db
.select("*")
.from("admins")
.leftJoin("bla")
.where("id", "in", [1, 2, 3, 4])
).map(({ id, name }) => ({ id, name }));
}
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.
<!-- Input -->
<template>
<template>foo</template>
</template>
<!-- Prettier 1.18 -->
<template>
<template
>foo</template
>
</template>
<!-- Prettier 1.19 -->
<template>
<template>foo</template>
</template>
Previously, in the whitespace-sensitive mode, they were formatted as if they were inline.
<!-- prettier-ignore --><!-- Input -->
<script
async
src="/_next/static/development/pages/_app.js?ts=1565732195968"
></script><script></script>
<!-- Prettier 1.18 -->
<script
async
src="/_next/static/development/pages/_app.js?ts=1565732195968"
></script
><script></script>
<!-- Prettier 1.19 -->
<script
async
src="/_next/static/development/pages/_app.js?ts=1565732195968"
></script>
<script></script>
! and other entities (#6785 by @lydell and @ikatyang)Previously, Prettier only supported the most common HTML entities, such as and ". Now, Prettier supports every HTML entity in the HTML spec, such as ! and ⋔.
<!-- Input -->
<p>Hi!</p>
<!-- Prettier 1.18
[error] stdin: SyntaxError: Unknown entity "excl" - use the "&#<decimal>;" or "&#x<hex>;" syntax (1:6)
[error] > 1 | <p>Hi!</p>
[error] | ^
[error] 2 |
-->
<!-- Prettier 1.19 -->
<p>Hi!</p>
<!-- Input -->
<script type="application/json">
{ "json":true }
</script>
<script type="importmap">
{ "json":true }
{ "json":true }
</script>
</script>
<script type="systemjs-importmap">
{ "json":true }
</script>
<!-- Prettier 1.18 -->
<script type="application/json">
{ "json":true }
</script>
<script type="importmap">
{ "json":true }
{ "json":true }
</script>
</script>
<script type="systemjs-importmap">
{ "json":true }
</script>
<!-- Prettier 1.19 -->
<script type="application/json">
{ "json": true }
</script>
<script type="importmap">
{ "json": true }
</script>
<script type="systemjs-importmap">
{ "json": true }
</script>
<!-- Input -->
{{ (isCustomDiscount ? 'DISCOUNTS__DISCOUNT_TRAINING_HEADER__CUSTOM_DISCOUNT' : 'DISCOUNTS__DISCOUNT_TRAINING_HEADER__DISCOUNT') | translate }}
<!-- Prettier 1.18 -->
{{
(isCustomDiscount
? "DISCOUNTS__DISCOUNT_TRAINING_HEADER__CUSTOM_DISCOUNT"
: "DISCOUNTS__DISCOUNT_TRAINING_HEADER__DISCOUNT") | translate
}}
<!-- Prettier 1.19 -->
{{
(isCustomDiscount
? "DISCOUNTS__DISCOUNT_TRAINING_HEADER__CUSTOM_DISCOUNT"
: "DISCOUNTS__DISCOUNT_TRAINING_HEADER__DISCOUNT"
) | translate
}}
i18n attributes (#6695 by @voithos)Prettier will auto-wrap the contents of i18n attributes once they exceed the line length.
<!-- Input -->
<h1 i18n="This is a very long internationalization description text, exceeding the configured print width">
Hello!
</h1>
<!-- Prettier 1.18 -->
<h1
i18n="This is a very long internationalization description text, exceeding the configured print width"
>
Hello!
</h1>
<!-- Prettier 1.19 -->
<h1
i18n="
This is a very long internationalization description text, exceeding the
configured print width
"
>
Hello!
</h1>
This fixes a variety of whitespace and line break use cases within Handlebars and Glimmer templates.
<!-- prettier-ignore --><!-- Input -->
<SomeComponent />{{name}}
Some sentence with {{dynamic}} expressions.
sometimes{{nogaps}}areimportant<Hello></Hello>
{{name}} is your name
<!-- Prettier 1.18 -->
<SomeComponent />
{{name}}
Some sentence with
{{dynamic}}
expressions.
sometimes
{{nogaps}}
areimportant
<Hello />
{{name}}
is your name
<!-- Prettier 1.19 -->
<SomeComponent />{{name}}
Some sentence with {{dynamic}} expressions.
sometimes{{nogaps}}areimportant
<Hello />
{{name}} is your name
Previously, Prettier added line breaks between text and mustaches which resulted in unwanted whitespace in rendered output.
<!-- prettier-ignore --><!-- Input -->
<p>Your username is @{{name}}</p>
<p>Hi {{firstName}} {{lastName}}</p>
<!-- Prettier 1.18 -->
<p>
Your username is @
{{name}}
</p>
<p>
Hi
{{firstName}}
{{lastName}}
</p>
<!-- Prettier 1.19 -->
<p>
Your username is @{{name}}
</p>
<p>
Hi {{firstName}} {{lastName}}
</p>
<!-- Input -->
<div>
{{! Foo }}
{{#if @foo}}
Foo
{{/if}}
{{! Bar }}
{{#if @bar}}
Bar
{{/if}}
</div>
<!-- Prettier 1.18 -->
<div>
{{! Foo }}
{{#if @foo}}
Foo
{{/if}}{{! Bar }}{{#if @bar}}
Bar
{{/if}}
</div>
<!-- Prettier 1.19 -->
<div>
{{! Foo }}
{{#if @foo}}
Foo
{{/if}}
{{! Bar }}
{{#if @bar}}
Bar
{{/if}}
</div>
<!-- Input -->
<p>
Some escaped characters: < > &
</p>
<!-- Prettier 1.18 -->
<p>
Some escaped characters: < > &
</p>
<!-- Prettier 1.19 -->
<p>
Some escaped characters: < > &
</p>
--single-quote option on HTML attributes (#6377 by @dcyriller)Previously, the flag was not applied on HTML attributes.
<!-- prettier-ignore --><!-- Input -->
<div class="a-class-name"></div>
<!-- Prettier 1.18, with the option --single-quote -->
<div class="a-class-name"></div>
<!-- Prettier 1.19, with the option --single-quote -->
<div class='a-class-name'></div>
<!-- Input -->
{{my-component foo="bar" bar="baz" action=(action "almostTheMaximumLengthxxxx")
}}
<!-- Prettier 1.18 -->
{{my-component foo="bar" bar="baz" action=(action "almostTheMaximumLengthxxxx")
}}
<!-- Prettier 1.19 -->
{{my-component
foo="bar"
bar="baz"
action=(action "almostTheMaximumLengthxxxx")
}}
<!-- Input -->
<Hello>
test <World /> test
</Hello> 123
<!-- Prettier 1.18 -->
<Hello>
test <World /> test
</Hello>123
<!-- Prettier 1.19 -->
<Hello>
test <World /> test
</Hello> 123
// Input
<Hello>
test <World /> test
</Hello>123
// Prettier 1.18
SyntaxError: Unexpected token (3:9)
1 | <Hello>
2 | test <World /> test
> 3 | </Hello>123
| ^
// Prettier 1.19
<Hello>
test <World /> test
</Hello>123
// Input
<Hello>
test <World /> test
</Hello>
<Hello>
test <World /> test
</Hello>123
// Prettier 1.18
SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>? (4:1)
2 | test <World /> test
3 | </Hello>
> 4 | <Hello>
| ^
5 | test <World /> test
6 | </Hello>123
// Prettier 1.19
<Hello>
test <World /> test
</Hello>
<Hello>
test <World /> test
</Hello>123
style[lang="css"] (#6875 by @fisker)Previously, <style> elements with lang="css" were not formatted, while omitting the attribute or setting to some other values worked. This oversight has been fixed.
<!-- Input -->
<style lang="css">
a {
color: #F00
}</style>
<!-- Output (Prettier stable) -->
<style lang="css">
a {
color: #F00
}
</style>
<!-- Output (Prettier master) -->
<style lang="css">
a {
color: #f00;
}
</style>
// Input
@FoO : bar;
// Prettier 1.18
@foo : bar;
// Prettier 1.19
@FoO: bar;
resolveConfig option to getFileInfo() (#6666 by @kaicataldo)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.
If you had an error in your .prettierrc Prettier used to crash when formatting stdin. Such errors are now handled properly.
# Prettier 1.18
$ prettier --parser babel < test.js
(node:21531) UnhandledPromiseRejectionWarning: Error: Invalid printWidth value. Expected an integer, but received "nope".
at _loop (/home/you/project/node_modules/prettier/bin-prettier.js:7887:63)
at Normalizer._applyNormalization (/home/you/project/node_modules/prettier/bin-prettier.js:8000:13)
at applyNormalization (/home/you/project/node_modules/prettier/bin-prettier.js:7817:49)
at Normalizer.normalize (/home/you/project/node_modules/prettier/bin-prettier.js:7823:9)
at normalizeOptions$1 (/home/you/project/node_modules/prettier/bin-prettier.js:8760:31)
at Object.normalizeApiOptions (/home/you/project/node_modules/prettier/bin-prettier.js:8918:10)
at getOptionsForFile (/home/you/project/node_modules/prettier/bin-prettier.js:44160:69)
at /home/you/project/node_modules/prettier/bin-prettier.js:44214:22
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:21531) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:21531) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
# Prettier 1.19
$ prettier --parser babel < test.js
[error] Invalid printWidth value. Expected an integer, but received "nope".
--stdin-filepath (#6687 by @voithos and @lydell)Previously, if you passed a nonexistent subdirectory to --stdin-filepath, Prettier would throw an error. Now, Prettier gracefully handles this.
# Prettier 1.18
$ prettier --stdin-filepath does/not/exist.js < test.js
[error] Invalid configuration file: ENOENT: no such file or directory, scandir '/home/you/project/does/not'
# Prettier 1.19
$ prettier --stdin-filepath does/not/exist.js < test.js
test;
Prior to this change, the CLI would resolve the config for a file before checking it against the ignored list. If the config was invalid, the CLI would report a failure.
This change relocates the config-resolution phase until after the file is confirmed to not be ignored.
# Input
$ prettier filename.js --config .invalid-config
# Prettier 1.18
Invalid configuration file: ...
# Prettier 1.19
Invalid configuration file `.invalid-config`: ...
Thanks to @fisker for updating lots of Prettier’s dependencies!
When using the Azure Cosmos DB extension for VS Code, you can create .mongo files to write MongoDB queries, which use Javascript syntax. This change allows VS Code to format your file using Prettier.
db.users.find({ someField: { $exists: true } });