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
espree
and meriyah
parser (#9000, #9514 by @fisker)
Add 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
TypeScript 4.1 (#9473, #9636 by @sosukesuzuki)
SupportKey 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
#8983 by @Monchi, @fisker)
ESM standalone bundles (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
#9078 by @sosukesuzuki)
Respect spacing between template values in embedded CSS (// 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};
`;
#9278 by @fisker)
Fix comments inside template literals with embedded syntax (// 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 */
}`;
#9341 by @sosukesuzuki)
Improve formatting for assignments of classes with long superclass names (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");
}
};
while
statements (#9345 by @sosukesuzuki)
Fix placement of leading comments for bodies of // Input
while(1) // Comment
foo();
// Prettier 2.1
while (
1 // Comment
)
foo();
// Prettier 2.2
while (1)
// Comment
foo();
@babel/parser
7.12 (#9408, #9476, #9597 by @sosukesuzuki)
Update to 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";
}
}
}
#9431 by @fisker)
Keep HTML and Markdown invalid template literals as is (// 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}`;
import {a as a}
and export {a as a}
(#9435 by @fisker)
Fix formatting for // 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";
#9650 by @brainkim)
Fix formatting of yielded JSX expressions (// 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>;
}
#9662 by @thorn0)
Flatten function expression parameters in hugged last argument (// 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");
}
);
}
require(/* comment */)
(#9670 by @fisker)
Fix crash on // Input
require(/* comment */)
// Prettier 2.1
Error: Comment "comment" was not printed. Please report this error!
// Prettier 2.2
require(/* comment */);
TypeScript
#9318 by @sosukesuzuki)
Preserve the last separator in ignored object types and interfaces (// 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;
};
#9484 by @fisker)
Add parens around assignments in object literal properties (// Input
foo = { bar: (a = b) };
// Prettier 2.1
foo = { bar: a = b };
// Prettier 2.2
foo = { bar: (a = b) };
typescript
and flow
(#9521 by @fisker)
Fix inconsistencies in formatting of types between // 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;
prettier-ignore
d mapped types (#9551 by @fisker)
Fix // 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
babel
parser to babel-flow
if the @flow
pragma is found (#9071 by @fisker)
Switch the 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 });
#9432 by @gkz)
Enums with unknown members (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;
BigIntLiteralTypeAnnotation
and BigIntTypeAnnotation
(#9523 by @fisker)
Support 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;
#9543 by @fisker)
Treat more simple types as non-breaking in generic type annotations (// 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;
prettier-ignore
d type assertions (#9553 by @fisker)
Fix missing parentheses around // 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))
);
#9563 by @fisker)
Improve comment types detection (// 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
#9356 by @thorn0)
Fix comments in value lists (// 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
Node.sourceSpan
(#9368 by @fisker)
Fix crash on reading <!-- 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
v-for
(#9225 by @zweimach)
Fix inconsistent formatting for <!-- 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>
script[setup]
and style[vars]
(#9609 by @fisker)
Fix inconsistent formatting for slots, support Vue 3
<!-- 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)
<Textarea />
(#9403 by @fisker, fixes in simple-html-tokenizer
by @rwjblue)
Fix unstable newlines after // Input
<Textarea />
{{#if true}}
Test
{{/if}}
// Prettier 2.1
<Textarea />
{{#if true}}
Test
{{/if}}
// Prettier 2.1 (second format)
<Textarea />
{{#if true}}
Test
{{/if}}
// Prettier 2.2
<Textarea />
{{#if true}}
Test
{{/if}}
Markdown
#7938 by @fisker and @thorn0)
Update remark-math to 3.0.1; escape dollar signs only if originally escaped (<!-- 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...
#8786 by @fisker)
Fix missing blank lines in fenced code blocks lacking the closing fence (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'
[[wiki-style]]
links (#9275 by @iamrecursion)
Add support for - 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.
#9365 by @kachkaev)
Align code block language detection with other popular tools (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" );
```
#9654 by @fisker)
Fix extra empty line added after empty table (<!-- 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
#9267 by @fisker)
Fix extra empty lines in JSX (<!-- 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
trailingComma
option (#9665 by @fisker)
Apply 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"
]
flowMapping
and flowSequence
(#9669 by @fisker)
Fix comments inside # 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
json
for .jsonl
files (#9371 by @fisker)
Stop inferring the parser to be // 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!
#9703 by @dangmai)
Flush line suffix contents at the end of document (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
pre-commit support to github.com/pre-commit/mirrors-prettier (#8937 by @FloChehab)
Movepre-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
#9298 by @fisker)
Fix: error on directories and files with numeric names ($ 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");