Prettier 2.2: new JavaScript parsers, TS 4.1 and ESM standalone bundles
This release supports new JavaScript parsers espree and meriyah, supports TypeScript 4.1, ships ESM standalone bundles for modern browsers, and includes many bug fixes and improvements!
Highlights
JavaScript
Add espree
and meriyah
parser (#9000, #9514 by @fisker)
Two new values for the parser
option has been added:
-
espree
- which is the default parser used byESLint
.Note that
espree
only works for Finished ECMAScript Proposals, and is stricter than thebabel
parser.
TypeScript
Support TypeScript 4.1 (#9473, #9636 by @sosukesuzuki)
Key Remapping In Mapped Types
// Input
type MappedTypeWithNewKeys<T> = {
[K in keyof T as NewKeyType]: T[K]
};
// Prettier 2.1
SyntaxError: Unexpected token, expected "]" (2:17)
1 | type MappedTypeWithNewKeys<T> = {
> 2 | [K in keyof T as NewKeyType]: T[K]
| ^
3 | };
// Prettier 2.2
type MappedTypeWithNewKeys<T> = {
[K in keyof T as NewKeyType]: T[K]
};
Template Literal Types
// Input
type HelloWorld = `Hello, ${keyof World}`
// Prettier 2.1
SyntaxError: Unexpected token, expected "}" (1:35)
> 1 | type HelloWorld = `Hello, ${keyof World}`
| ^
// Prettier 2.2
type HelloWorld = `Hello, ${keyof World}`;
API
ESM standalone bundles (#8983 by @Monchi, @fisker)
Prettier now also comes as ES modules, which can be directly used in modern browsers:
import prettier from "https://unpkg.com/prettier/esm/standalone.mjs";
import parserGraphql from "https://unpkg.com/prettier/esm/parser-graphql.mjs";
prettier.format("query { }", {
parser: "graphql",
plugins: [parserGraphql],
});
Other changes
JavaScript
Respect spacing between template values in embedded CSS (#9078 by @sosukesuzuki)
// Input
const style = css`
width: ${size}${sizeUnit};
`;
// Prettier 2.1
const style = css`
width: ${size} ${sizeUnit};
`;
// Prettier 2.2
const style = css`
width: ${size}${sizeUnit};
`;
Fix comments inside template literals with embedded syntax (#9278 by @fisker)
// Input
html`${
foo
/* comment */
}`;
html`
${
foo
/* comment */
}
`;
graphql`${
foo
/* comment */
}`;
css`${
foo
/* comment */
}`;
// Prettier 2.1
html`${foo}`;
/* comment */
html`
${foo}
/* comment */
`;
graphql`
${foo}
/* comment */
`;
css`
${foo}
/* comment */
`;
// Prettier 2.2
html`${
foo
/* comment */
}`;
html`
${
foo
/* comment */
}
`;
graphql`${
foo
/* comment */
}`;
css`${
foo
/* comment */
}`;
Improve formatting for assignments of classes with long superclass names (#9341 by @sosukesuzuki)
This improves the formatting for Google Closure Library namespaces.
// Input
aaaaaaaa.bbbbbbbb.cccccccc.dddddddd.eeeeeeee.ffffffff.gggggggg2 = class extends (
aaaaaaaa.bbbbbbbb.cccccccc.dddddddd.eeeeeeee.ffffffff.gggggggg1
) {
method () {
console.log("foo");
}
};
// Prettier 2.1
aaaaaaaa.bbbbbbbb.cccccccc.dddddddd.eeeeeeee.ffffffff.gggggggg2 = class extends aaaaaaaa
.bbbbbbbb.cccccccc.dddddddd.eeeeeeee.ffffffff.gggggggg1 {
method() {
console.log("foo");
}
};
// Prettier 2.2
aaaaaaaa.bbbbbbbb.cccccccc.dddddddd.eeeeeeee.ffffffff.gggggggg2 = class extends (
aaaaaaaa.bbbbbbbb.cccccccc.dddddddd.eeeeeeee.ffffffff.gggggggg1
) {
method() {
console.log("foo");
}
};
Fix placement of leading comments for bodies of while
statements (#9345 by @sosukesuzuki)
// Input
while(1) // Comment
foo();
// Prettier 2.1
while (
1 // Comment
)
foo();
// Prettier 2.2
while (1)
// Comment
foo();
Update to @babel/parser
7.12 (#9408, #9476, #9597 by @sosukesuzuki)
Updated the JavaScript parser to @babel/parser
7.12. This fixes several bugs and supports some new syntax.
Support Import Assertions
The "module attributes" proposal supported on 2.1 has been significantly changed and also renamed to "import assertions".
import foo from "./foo.json" assert { type: "json" };
Support imports and exports with string names
let happy = "happy";
export { happy as "😃" };
Support class static blocks
class C {
static #x = 42;
static y;
static {
try {
this.y = doSomethingWith(this.#x);
} catch {
this.y = "unknown";
}
}
}
Keep HTML and Markdown invalid template literals as is (#9431 by @fisker)
// Input
foo = html`<div>\u{prettier}</div>`;
foo = html`\u{prettier}${foo}pr\u{0065}ttier`;
foo = markdown`# \u{prettier}\u{0065}`;
// Prettier 2.1
foo = html``;
foo = html`null${foo}prettier`;
foo = markdown`
# \u{prettier}\u{0065}
`;
// Prettier 2.2
foo = html`<div>\u{prettier}</div>`;
foo = html`\u{prettier}${foo}pr\u{0065}ttier`;
foo = markdown`# \u{prettier}\u{0065}`;
Fix formatting for import {a as a}
and export {a as a}
(#9435 by @fisker)
// Input
import { a as a } from "a";
export { b as b } from "b";
// Prettier 2.1
import { a } from "a";
export { b } from "b";
// Prettier 2.2
import { a as a } from "a";
export { b as b } from "b";
Fix formatting of yielded JSX expressions (#9650 by @brainkim)
// Input
function* f() {
yield <div>generator</div>
}
// Prettier 2.1
function* f() {
yield (<div>generator</div>);
}
// Prettier 2.2
function* f() {
yield <div>generator</div>;
}
Flatten function expression parameters in hugged last argument (#9662 by @thorn0)
// Prettier 2.1
function* mySagas() {
yield effects.takeEvery(rexpress.actionTypes.REQUEST_START, function* ({
id
}) {
console.log(id);
yield rexpress.actions(store).writeHead(id, 400);
yield rexpress.actions(store).end(id, "pong");
console.log("pong");
});
}
// Prettier 2.2
function* mySagas() {
yield effects.takeEvery(
rexpress.actionTypes.REQUEST_START,
function* ({ id }) {
console.log(id);
yield rexpress.actions(store).writeHead(id, 400);
yield rexpress.actions(store).end(id, "pong");
console.log("pong");
}
);
}
Fix crash on require(/* comment */)
(#9670 by @fisker)
// Input
require(/* comment */)
// Prettier 2.1
Error: Comment "comment" was not printed. Please report this error!
// Prettier 2.2
require(/* comment */);
TypeScript
Preserve the last separator in ignored object types and interfaces (#9318 by @sosukesuzuki)
// Input
let x: {
// prettier-ignore
y: z;
};
// Prettier 2.1
let x: {
// prettier-ignore
y: z;;
};
// Prettier 2.2
let x: {
// prettier-ignore
y: z;
};
Add parens around assignments in object literal properties (#9484 by @fisker)
// Input
foo = { bar: (a = b) };
// Prettier 2.1
foo = { bar: a = b };
// Prettier 2.2
foo = { bar: (a = b) };
Fix inconsistencies in formatting of types between typescript
and flow
(#9521 by @fisker)
// Input
const name: SomeGeneric<
Pick<Config, "ONE_LONG_PROP" | "ANOTHER_LONG_PROP">
> = null;
// Prettier 2.1 (--parser=typescript)
const name: SomeGeneric<Pick<
Config,
"ONE_LONG_PROP" | "ANOTHER_LONG_PROP"
>> = null;
// Prettier 2.1 (--parser=flow)
const name: SomeGeneric<
Pick<Config, "ONE_LONG_PROP" | "ANOTHER_LONG_PROP">
> = null;
// Prettier 2.2 (typescript and flow parser)
const name: SomeGeneric<
Pick<Config, "ONE_LONG_PROP" | "ANOTHER_LONG_PROP">
> = null;
Fix prettier-ignore
d mapped types (#9551 by @fisker)
// Input
type a= {
// prettier-ignore
[A in B]: C | D
}
// Prettier 2.1
type a = {
// prettier-ignore
A in B: C | D;
};
// Prettier 2.2
type a = {
// prettier-ignore
[A in B]: C | D
};
Flow
Switch the babel
parser to babel-flow
if the @flow
pragma is found (#9071 by @fisker)
In practice, this means that as long as your Flow files have the pragma, it's safe to use the .js
extension for them. Prettier will correctly parse and print them without any additional configuration. Previously, the pragma was recognized by the parser, but there existed minor correctness issues with the printer. E.g. it's not safe to unquote number keys in Flow.
// Input (with --parser babel)
// @flow
f<T>({ "2": 2 })
// Prettier 2.1
// @flow
f<T>({ 2: 2 });
// Prettier 2.2
// @flow
f<T>({ "2": 2 });
Enums with unknown members (#9432 by @gkz)
Previously, was not supported. Now, the following is formatted:
// Input
enum E {
A,
B,
...
}
// Prettier 2.1: parse error
// Prettier 2.2
enum E {
A,
B,
...
}
this
parameter annotations (#9457 by @dsainati1, #9489 by @fisker)
// Input
function f(this: string, a: number) {
}
type T = (this: boolean, a: number) => boolean;
// Prettier 2.1
function f(this: string, a: number) {}
type T = (a: number) => boolean;
// Prettier 2.2
function f(this: string, a: number) {
}
type T = (this: boolean, a: number) => boolean;
Support BigIntLiteralTypeAnnotation
and BigIntTypeAnnotation
(#9523 by @fisker)
Add support for BigIntLiteralTypeAnnotation
and BigIntTypeAnnotation
in Flow.
// Input
const foo: bigint = 1n;
const bar: baz<1n> = 1n;
// Prettier 2.1
Error: unknown type: "BigIntTypeAnnotation"
at ...
// Prettier 2.2
const foo: bigint = 1n;
const bar: baz<1n> = 1n;
Treat more simple types as non-breaking in generic type annotations (#9543 by @fisker)
// Input
const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<symbol> = a
const foo2: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<"STRING"> = a;
const foo3: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0> = a;
// Prettier 2.1
const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<
symbol
> = a;
const foo2: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<
"STRING"
> = a;
const foo3: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<
0
> = a;
// Prettier 2.2 (typescript and flow parser)
const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<symbol> = a
const foo2: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<"STRING"> = a;
const foo3: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0> = a;
Fix missing parentheses around prettier-ignore
d type assertions (#9553 by @fisker)
// Input
transform(
// prettier-ignore
(pointTransformer: (Point => Point))
);
// Prettier 2.1
transform(
// prettier-ignore
pointTransformer: (Point => Point)
);
// Prettier 2.2
transform(
// prettier-ignore
(pointTransformer: (Point => Point))
);
Improve comment types detection (#9563 by @fisker)
// Input
foo/*::<bar>*/(baz);
class Foo {
bar( data: Array<string>) {}
}
// Prettier 2.1
foo/*:: <bar> */(baz);
class Foo {
bar(data: Array/*:: <string> */) {}
}
// Prettier 2.2
foo/*:: <bar> */(baz);
class Foo {
bar(data: Array<string>) {}
}
Less
Fix comments in value lists (#9356 by @thorn0)
// Input
@test-space-separated: #aaaaaa // Start with A
#bbbbbb // then some B
#cccccc; // and round it out with C
// Prettier 2.1
@test-space-separated: #aaaaaa a // Start with
#bbbbbb b // then some
#cccccc; // and round it out with C
// Prettier 2.2
@test-space-separated: #aaaaaa // Start with A
#bbbbbb // then some B
#cccccc; // and round it out with C
HTML
Fix crash on reading Node.sourceSpan
(#9368 by @fisker)
<!-- Input -->
<strong>a</strong>-<strong>b</strong>-
<!-- Prettier 2.1 -->
TypeError: Cannot read property 'line' of undefined
at forceNextEmptyLine ...
<!-- Prettier 2.2 -->
<strong>a</strong>-<strong>b</strong>-
Vue
Fix inconsistent formatting for v-for
(#9225 by @zweimach)
<!-- Input -->
<template>
<div
v-for="({ longLongProp=42, anotherLongLongProp='Hello, World!' }, index) of longLongLongLongLongLongLongLongList"
></div>
<div
v-for="({firstValue, secondValue, thirdValue, fourthValue, fifthValue, sixthValue}, objectKey, index) in objectWithAVeryVeryVeryVeryLongName"
></div>
</template>
<!-- Prettier 2.1 -->
<template>
<div
v-for="({ longLongProp = 42, anotherLongLongProp = 'Hello, World!' },
index) of longLongLongLongLongLongLongLongList"
></div>
<div
v-for="({
firstValue,
secondValue,
thirdValue,
fourthValue,
fifthValue,
sixthValue,
},
objectKey,
index) in objectWithAVeryVeryVeryVeryLongName"
></div>
</template>
<!-- Prettier 2.2 -->
<template>
<div
v-for="(
{ longLongProp = 42, anotherLongLongProp = 'Hello, World!' }, index
) of longLongLongLongLongLongLongLongList"
></div>
<div
v-for="(
{
firstValue,
secondValue,
thirdValue,
fourthValue,
fifthValue,
sixthValue,
},
objectKey,
index
) in objectWithAVeryVeryVeryVeryLongName"
></div>
</template>
Fix inconsistent formatting for slots, support Vue 3 script[setup]
and style[vars]
(#9609 by @fisker)
<!-- Input -->
<script setup="props, {emit }"></script>
<style vars="{color }"></style>
<template>
<div>
<div v-slot="{destructuring:{ a:{b}}}"/>
<div v-slot:name="{destructuring:{ a:{b}}}"/>
<div #default="{destructuring:{ a:{b}}}"/>
<slot slot-scope="{destructuring:{ a:{b}}}"/>
</div>
</template>
<!-- Prettier 2.1 -->
<script setup="props, {emit }"></script>
<style vars="{color }"></style>
<template>
<div>
<div v-slot="{ destructuring: { a: { b } } }" />
<div v-slot:name="{ destructuring: { a: { b } } }" />
<div #default="{ destructuring: { a: { b } } }" />
<slot
slot-scope="{
destructuring: {
a: { b },
},
}"
/>
</div>
</template>
<!-- Prettier 2.2 -->
<script setup="props, { emit }"></script>
<style vars="{ color }"></style>
<template>
<div>
<div
v-slot="{
destructuring: {
a: { b },
},
}"
/>
<div
v-slot:name="{
destructuring: {
a: { b },
},
}"
/>
<div
#default="{
destructuring: {
a: { b },
},
}"
/>
<slot
slot-scope="{
destructuring: {
a: { b },
},
}"
/>
</div>
</template>
Handlebars (alpha)
Fix unstable newlines after <Textarea />
(#9403 by @fisker, fixes in simple-html-tokenizer
by @rwjblue)
Markdown
Update remark-math to 3.0.1; escape dollar signs only if originally escaped (#7938 by @fisker and @thorn0)
<!-- Input -->
Paragraph with $14 million.
Paragraph with $14 million. But if more $dollars on the same line...
<!-- Prettier 2.1 -->
Paragraph with \$14 million.
Paragraph with $14 million. But if more $dollars on the same line...
<!-- Prettier 2.2 -->
Paragraph with $14 million.
Paragraph with $14 million. But if more $dollars on the same line...
Fix missing blank lines in fenced code blocks lacking the closing fence (#8786 by @fisker)
require("prettier").format("```a\n\n\n\n", { parser: "markdown" });
<!-- Prettier 2.1 -->
'```a\n\n```\n'
<!-- Prettier 2.2 -->
'```a\n\n\n\n```\n'
Add support for [[wiki-style]]
links (#9275 by @iamrecursion)
- Support for
[[wiki-style]]
links ensures that they do not get broken by the prettier formatting by being wrapped over multiple lines. - The contents of the link (between the
[[]]
brackets) are treated as raw text. This is because the various tools that rely on the[[]]
syntax do not agree on what is allowable between them.
<!-- Input -->
If I have a prose that forces a wiki link to end up crossing the [[line width limit]] like this. It's wrapped into an invalid state.
<!-- Prettier 2.1 -->
If I have a prose that forces a wiki link to end up crossing the [[line width
limit]] like this. It's wrapped into an invalid state.
<!-- Prettier 2.2 -->
If I have a prose that forces a wiki link to end up crossing the
[[line width limit]] like this. It's wrapped into an invalid state.
Align code block language detection with other popular tools (#9365 by @kachkaev)
Since Prettier 1.12, code blocks starting like ```js {something=something}
are detected as JavaScript ones and are therefore formatted.
Back in the day, not many tools used to separate the language from the metadata, so it was decided to make whitespace optional and thus detect ```js{something=something}
as JavaScript too.
With the release of Remark v8 (which is used by Prettier), code block language detection and formatting became inconsistent in several rare edge cases. Besides, it was noticed that Prettier‘s formatting behaviour mismatched syntax highlighting in VSCode. To encourage consistency between different tools and to better align with the Commonmark spec, use of whitespace between the language name and the metadata was made compulsory.
<!-- Input -->
```js {something=something}
console.log ( "hello world" );
```
```js{something=something}
console.log ( "hello world" );
```
<!-- Prettier 2.1 -->
```js {something=something}
console.log("hello world");
```
```js{something=something}
console.log("hello world");
```
<!-- Prettier 2.2 -->
```js {something=something}
console.log("hello world");
```
```js{something=something}
console.log ( "hello world" );
```
Fix extra empty line added after empty table (#9654 by @fisker)
<!-- Input -->
Test line 1
| Specify the selected option : | Option 1 |
| ----------------------------- | -------- |
Test line 6
<!-- Prettier 2.1 -->
Test line 1
| Specify the selected option : | Option 1 |
| ----------------------------- | -------- |
Test line 6
<!-- Prettier 2.2 -->
Test line 1
| Specify the selected option : | Option 1 |
| ----------------------------- | -------- |
Test line 6
MDX
Fix extra empty lines in JSX (#9267 by @fisker)
<!-- Input -->
# title
<Jsx>
text
</Jsx>
<!-- Prettier 2.1 -->
# title
<Jsx>
text
</Jsx>
(Extra empty lines added after `<Jsx>` and `</Jsx>`)
<!-- Prettier 2.2 -->
# title
<Jsx>
text
</Jsx>
YAML
Apply trailingComma
option (#9665 by @fisker)
When --trailing-comma=none
, should not add trailing comma to flowMapping and flowSequence.
# Input
flow-mapping:
{
"object-does-not-fit-within-print-width": "------",
"TEST": "comma IS added here"
}
flow-sequence:
[
"object-does-not-fit-within-print-width", "------",
"TEST", "comma IS added here"
]
# Prettier 2.1
mapping:
{
"object-does-not-fit-within-print-width": "------",
"TEST": "comma IS added here",
}
flow-sequence:
[
"object-does-not-fit-within-print-width",
"------",
"TEST",
"comma IS added here",
]
# Prettier 2.2
flow-mapping:
{
"object-does-not-fit-within-print-width": "------",
"TEST": "comma IS added here"
}
flow-sequence:
[
"object-does-not-fit-within-print-width",
"------",
"TEST",
"comma IS added here"
]
Fix comments inside flowMapping
and flowSequence
(#9669 by @fisker)
# Input
a:
[
a, b,
# comment
]
b:
# prettier-ignore
{
a: 1, b: 2,
# comment
}
# Prettier 2.1
a: [a, b]
# comment
b:
# prettier-ignore
{
a: 1, b: 2,
# comment
}
# comment
# Prettier 2.1 (second format)
a:
[a, b]
# comment
b:
# prettier-ignore
{
a: 1, b: 2,
# comment
}
# comment
# comment
# Prettier 2.2
a: [
a,
b,
# comment
]
b:
# prettier-ignore
{
a: 1, b: 2,
# comment
}
API
Stop inferring the parser to be json
for .jsonl
files (#9371 by @fisker)
// Prettier 2.1
$ prettier --check .
Checking formatting...
[error] bad.jsonl: SyntaxError: Unexpected token (2:1)
[error] 1 | '{"type": "t/f", "head": "England", "relation": "invaded", "tail": "United States"}'
[error] > 2 | '{"type": "t/f", "head": "England", "relation": "attacked", "tail": "Baltimore"}'
[error] | ^
[error] 3 |
All matched files use Prettier code style!
// Prettier 2.2
$ prettier --check .
Checking formatting...
All matched files use Prettier code style!
Flush line suffix contents at the end of document (#9703 by @dangmai)
Prettier did not flush line-suffix contents at the end of the document if there was no trailing newline. This fix forces all of those contents to be flushed even without trailing newlines.
CLI
Move pre-commit support to github.com/pre-commit/mirrors-prettier (#8937 by @FloChehab)
pre-commit
support has moved to https://github.com/pre-commit/mirrors-prettier, please update your .pre-commit-config.yaml
file .
- - repo: https://github.com/prettier/prettier
+ - repo: https://github.com/pre-commit/mirrors-prettier
- rev: "2.2.0"
+ rev: "v2.2.0"
hooks:
- id: prettier
Fix: error on directories and files with numeric names (#9298 by @fisker)
$ cat 1/index.js
hello('world')
// Prettier 2.1
$ prettier 1
[error] The "path" argument must be of type string. Received type number (1)
// Prettier 2.2
$ prettier 1
hello("world");