website/blog/2018-04-11-1.12.0.md
Hello everyone, and welcome to Prettier 1.12.0! This release contains a lot of bugfixes, formatting adjustments, new features for our plugin API, and new Markdown features.
<!-- truncate -->When ternaries are nested, depending on the print width and indentation level, sometimes the outer ternary could get broken across multiple lines, while the inner ternary was left on one line:
<!-- prettier-ignore -->// Input:
const platformString = Platform.OS == "ios" ? "iOS"
: Platform.OS == "android" ? "Android" : "unknown";
// Formatted (Prettier 1.11.1):
const platformString =
Platform.OS == "ios"
? "iOS"
: Platform.OS == "android" ? "Android" : "unknown";
This looked a bit odd, so to increase readability, we will now make all nested ternaries multi-line if any of them become multiline:
<!-- prettier-ignore -->// Formatted (Prettier 1.12.0):
const platformString =
Platform.OS == "ios"
? "iOS"
: Platform.OS == "android"
? "Android"
: "unknown";
else (#4264 by @duailibe)A bug that has been open for a long time deals with the behavior around printing comments before else. Comments before the else keyword were moved inside the else block, which could be confusing when the comment was explaining the condition instead of the block. Additionally, it got in the way when commenting out a portion of an if/else chain.
if (obj.foo) {
return foo;
}
// Use bar as a fallback
else if (obj.bar) {
return bar;
}
if (a == 2) {
console.log('2');
}
// else if (a == 3) {
// console.log('3');
// }
else if (a == 4) {
console.log('4');
}
if (obj.foo) {
return foo;
} else if (obj.bar) {
// Use bar as a fallback
return bar;
}
if (a == 2) {
console.log("2");
} else if (a == 4) {
// else if (a == 3) {
// console.log('3');
// }
console.log("4");
}
It was annoying that these comments got moved, but we weren't sure what to do here because we wanted to consistently format else blocks in this style: } else {.
We decided with this release to make an exception to the normal formatting and format else differently, but only if a comment appears in-between the else and the opening brace. This seems like the best solution:
if (obj.foo) {
return foo;
}
// Use bar as a fallback
else if (obj.bar) {
return bar;
}
if (a == 2) {
console.log("2");
}
// else if (a == 3) {
// console.log('3');
// }
else if (a == 4) {
console.log("4");
}
In Prettier 1.11.1, Angular tests using the async testing helper were formatted with an unnecessary number of line breaks. We've made a change to keep functions wrapped with this helper in-line, which prevents these unnecessary line breaks.
// Input:
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent]
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});
// Formatted (Prettier 1.11.1):
import { TestBed, async } from "@angular/core/testing";
import { AppComponent } from "./app.component";
describe("AppComponent", () => {
beforeEach(
async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent]
}).compileComponents();
})
);
it(
"should create the app",
async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
})
);
});
// Formatted (Prettier 1.12.0):
import { TestBed, async } from "@angular/core/testing";
import { AppComponent } from "./app.component";
describe("AppComponent", () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent]
}).compileComponents();
}));
it("should create the app", async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});
ObjectPatterns with nested ObjectPatterns (#4267 by @duailibe)We received a lot of community feedback that object and array destructuring syntax sometimes did not format very well. As a first step towards improving this, we have made a change so that any nested non-leaf object or array patterns in a destructuring pattern will get multi-lined if any of their parents do:
<!-- prettier-ignore -->// Input:
const {
name: {
first,
last,
},
organisation: {
address: {
street: orgStreetAddress,
postcode: orgPostcode,
},
},
} = user;
// Formatted (Prettier 1.11.1):
const {
name: { first, last },
organisation: { address: { street: orgStreetAddress, postcode: orgPostcode } }
} = user;
// Formatted (Prettier 1.12.0):
const {
name: { first, last },
organisation: {
address: { street: orgStreetAddress, postcode: orgPostcode }
}
} = user;
Prettier 1.7.0 and 1.8.0 introduced two new options, --require-pragma and --insert-pragma. However, these options were only supported in JavaScript. Now these options are available in Markdown, too!
<!-- @prettier -->
# My Markdown Document
A long time ago, in my hometown of Ericsburgh...
prettier-ignore-start/prettier-ignore-end (#4202 by @ikatyang)When using tools such as all-contributors or markdown-toc, users were running into situations where autogenerated Markdown content was formatted oddly by Prettier, or Prettier's --list-different mode was flagging autogenerated content that the user didn't care about formatting.
To solve these problems, we have added a new type of ignore comment to Markdown, called Range Ignore:
<!-- prettier-ignore --><!-- prettier-ignore-start -->
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
| [
<sub><b>Alice</b></sub>](https://github.com/example-alice)
[💻](https://github.com/my/repo/commits?author=example-alice "Code") [📖](https://github.com/my/repo/commits?author=example-alice "Documentation") [⚠️](https://github.com/my/repo/commits?author=example-alice "Tests") | [
<sub><b>Bob</b></sub>](https://github.com/example-bob)
[🐛](https://github.com/my/repo/issues?q=author%3Aexample-bob "Bug reports") | [
<sub><b>Jeffrey</b></sub>](https://github.com/example-jeffrey)
[🐛](https://github.com/my/repo/issues?q=author%3Aexample-jeffrey "Bug reports") | [
<sub><b>Sarah</b></sub>](https://github.com/example-sarah)
[🐛](https://github.com/my/repo/issues?q=author%3Aexample-sarah "Bug reports") |
| :---: | :---: | :---: | :---: |
<!-- ALL-CONTRIBUTORS-LIST:END -->
<!-- prettier-ignore-end -->
You can put prettier-ignore-start and prettier-ignore-end comments around autogenerated content, and prettier will ignore everything in-between. Please note that this feature is currently only available in Markdown, and can only be used at the top-level.
The GraphQL Schema Definition Language recently changed the syntax for multiple inherited interfaces to use & instead of ,:
// Old style
type Foo implements Bar, Baz { field: Type }
// New style
type Foo implements Bar & Baz { field: Type }
Prettier 1.11.1 failed to parse the new style; we now support both styles.
Prettier plugins can now include a hasPragma function in their parser and an insertPragma function in their printer to opt-in to --insert-pragma and --require-pragma support. These are their signatures:
function hasPragma(text: string): boolean;
function insertPragma(text: string): string;
Plugins can now override prettier's built-in comment printing algorithm on a case-by-case basis in order to better support comment formatting for their language. This API is not yet documented, but you can view how this feature is used in the recently-released Prettier PHP Plugin here and here.
Optional chaining (?.) is now supported when using the flow parser:
const name = this.model?.user?.firstName || "No Name Set"
This change fixes a bug where ignored comments in named exports were duplicated on every format:
<!-- prettier-ignore -->// Input:
// prettier-ignore
export {
foo, // comment
bar, // comment
}
// Formatted (Prettier 1.11.1):
// prettier-ignore
// comment
// comment
export {
foo, // comment
bar, // comment
}
// Formatted (Prettier 1.12.0):
// prettier-ignore
export {
foo, // comment
bar, // comment
}
Prettier was mistakenly not printing some comments near the continue and break keywords. This has been fixed:
// Input:
for (let i = 0; i < 5; i++) {
continue /* Comment */;
}
for (let i = 0; i < 10; i++) {
break /* Comment */;
}
// Output (Prettier 1.11.1):
/*
Error: Comment "Comment" was not printed. Please report this error!
at https://prettier.io/lib/index.js:2312:75
at Array.forEach (<anonymous>)
at ensureAllCommentsPrinted (https://prettier.io/lib/index.js:2312:22)
at _formatWithCursor (https://prettier.io/lib/index.js:2313:949)
at _format (https://prettier.io/lib/index.js:2314:239)
at formatRange (https://prettier.io/lib/index.js:2331:215)
at _formatWithCursor (https://prettier.io/lib/index.js:2313:288)
at _format (https://prettier.io/lib/index.js:2314:239)
at Object.format (https://prettier.io/lib/index.js:2333:277)
at formatCode (https://prettier.io/worker.js:130:21)
at self.onmessage (https://prettier.io/worker.js:80:19)
*/
// Formatted (Prettier 1.12.0):
for (let i = 0; i < 5; i++) {
continue; /* Comment */
}
for (let i = 0; i < 10; i++) {
break; /* Comment */
}
In Prettier 1.11.1, a bug caused GraphQL containing escaped backtick strings to not be formatted. This has been fixed in Prettier 1.12.0:
<!-- prettier-ignore -->// Input:
gql`
"\`foo\` mutation payload."
type FooPayload { bar: String
}
`
// Formatted (Prettier 1.11.1):
gql`
"\`foo\` mutation payload."
type FooPayload { bar: String
}
`;
// Formatted (Prettier 1.12.0):
gql`
"\`foo\` mutation payload."
type FooPayload {
bar: String
}
`;
prettier-ignore inside template literal (#4220 by @evilebottnawi)A bug in Prettier 1.11.1 caused expressions nested in template literals to get moved around when using prettier-ignore comments within the literal, under certain conditions:
// Input:
styled.div`
color: ${props => props.theme.colors.paragraph};
/* prettier-ignore */
${props => props.small ? 'font-size: 0.8em;' : ''};
`
// Formatted (Prettier 1.11.1):
styled.div`
color: ${props => (props.small ? "font-size: 0.8em;" : "")};
/* prettier-ignore */
${props => props.theme.colors.paragraph};
`;
Note that the two functions receiving props have switched places.
This bug has been fixed in prettier 1.12.0:
<!-- prettier-ignore -->// Formatted (Prettier 1.12.0):
styled.div`
color: ${props => props.theme.colors.paragraph};
/* prettier-ignore */
${props => (props.small ? "font-size: 0.8em;" : "")};
`;
In Prettier 1.11.1, there was an issue where the indentation level for binary expressions (things like 2 + 2, 4 * 4, etc) would increase with each line break under certain conditions. This has been fixed in Prettier 1.12.0:
// Input:
class EnterpriseQualityClass {
foobar =
// we get foo and multiply by 3
this.foo * 3 +
// then add bar and multiply by 90 time foo plus 2
(this.bar * 90) * (this.foo + 2)
}
// Formatted (Prettier 1.11.1):
class EnterpriseQualityClass {
foobar =
// we get foo and multiply by 3
this.foo * 3 +
// then add bar and multiply by 90 time foo plus 2
this.bar * 90 * (this.foo + 2);
}
// Formatted (Prettier 1.12.0):
class EnterpriseQualityClass {
foobar =
// we get foo and multiply by 3
this.foo * 3 +
// then add bar and multiply by 90 time foo plus 2
this.bar * 90 * (this.foo + 2);
}
When the discriminant of a switch statement was very long, we were not printing it very pretty. The formatting has been improved in Prettier 1.12.0:
<!-- prettier-ignore -->// Input:
switch (longLongLongLongLongLongLongVariable &&
longLongLongLongLongLongLongVariable) {
case (1): {
console.log("hi");
}
}
// Formatted (Prettier 1.11.1):
switch (longLongLongLongLongLongLongVariable &&
longLongLongLongLongLongLongVariable) {
case 1: {
console.log("hi");
}
}
// Formatted (Prettier 1.12.0):
switch (
longLongLongLongLongLongLongVariable && longLongLongLongLongLongLongVariable
) {
case 1: {
console.log("hi");
}
}
export default interface Foo {} (#4128 by @j-f1)In Prettier 1.11.1, semicolons were mistakenly printed after default-exported interfaces. This has been resolved in Prettier 1.12.0:
<!-- prettier-ignore -->// Input:
export default interface Foo {
readonly bar?: string;
}
// Formatted (Prettier 1.11.1):
export default interface Foo {
readonly bar?: string;
};
// Formatted (Prettier 1.12.0):
export default interface Foo {
readonly bar?: string;
}
Prettier 1.11.1 was mistakenly removing parens around typecast update expressions, which caused a syntax error. This issue has been fixed in Prettier 1.12.0:
<!-- prettier-ignore -->// Input:
(obj.value as any)++
// Formatted (Prettier 1.11.1):
obj.value as any++;
// Formatted (Prettier 1.12.0):
(obj.value as any)++;
Prettier 1.11.1 was printing an unnecessary empty line when formatting a markdown document containing empty yaml/toml front-matter; this line is no longer printed:
---
---
Hello
---
---
Hello
---
---
Hello
Some markdown documents use attributes listed after the language for special purposes; for example, they are used by markdown-preview-enhanced to modify display options and specify code execution parameters.
Code block language attributes look like this:
<!-- prettier-ignore -->```js {cmd=node .line-numbers}
console.log("hello world");
```
Prettier was not formatting the contents of these markdown blocks before, because it could no longer detect the language of a code block when attributes were present. Now, prettier correctly detects the language.
In Prettier 1.11.1, HTML nested underneath a list item was not formatted correctly; the indentation level changed each time you re-formatted the code. This is now fixed.
<!-- prettier-ignore --><!-- Input: -->
1. A list item
<table class="table table-striped">
<tr>
<th>Test</th>
<th>Table</th>
</tr>
<tbody>
<tr>
<td>Test</td>
<td>Data</td>
</tr>
</tbody>
</table>
<!-- Output (Prettier 1.11.1): -->
1. A list item
<table class="table table-striped">
<tr>
<th>Test</th>
<th>Table</th>
</tr>
<tbody>
<tr>
<td>Test</td>
<td>Data</td>
</tr>
</tbody>
</table>
<!-- Output (Prettier 1.12.0): -->
1. A list item
<table class="table table-striped">
<tr>
<th>Test</th>
<th>Table</th>
</tr>
<tbody>
<tr>
<td>Test</td>
<td>Data</td>
</tr>
</tbody>
</table>
In Prettier 1.11.1, when embedding CSS or JSX in markdown, there was an issue that caused the indentation level of block comments to be set incorrectly in some situations. This issue has been fixed in Prettier 1.12.0:
<!-- prettier-ignore --><!-- Input: -->
```pcss
.Avatar {
@container (width > 100px) {
/*
Change some styles on the image element when the container is
wider than 100px
*/
}
}
```
<!-- Formatted (Prettier 1.11.1): -->
```pcss
.Avatar {
@container (width > 100px) {
/*
Change some styles on the image element when the container is
wider than 100px
*/
}
}
```
<!-- Formatted (Prettier 1.12.0): -->
```pcss
.Avatar {
@container (width > 100px) {
/*
Change some styles on the image element when the container is
wider than 100px
*/
}
}
```
Prettier 1.11.1 was mistakenly changing the variable name of custom selectors to be lower-case. This issue has been fixed in Prettier 1.12.0:
<!-- prettier-ignore -->/* Input: */
@custom-selector :--camelCase .my-css-selector;
:--camelCase {
color: red;
}
/* Formatted (Prettier 1.11.1): */
@custom-selector :--camelCase .my-css-selector;
:--camelcase {
color: red;
}
/* Formatted (Prettier 1.12.0): */
@custom-selector :--camelCase .my-css-selector;
:--camelCase {
color: red;
}
In Prettier 1.11.1, there was an issue where Prettier would print url()s incorrectly when they appeared in shorthand properties. This has been fixed in Prettier 1.12.0.
/* Input: */
.search-icon {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8cGF0aCBkPSJNMTMuNzQzIDEyLjU3NEw5LjkxIDguNzRhNS40MjUgNS40MjUgMCAwIDAgMS4wNS0zLjIzMkE1LjUzMiA1LjUzMiAwIDAgMCA1LjQ2IDAgNS40MzYgNS40MzYgMCAwIDAgMCA1LjQ2OGE1LjUzMiA1LjUzMiAwIDAgMCA1LjUgNS41MDggNS40MDggNS40MDggMCAwIDAgMy4yNDItMS4wNjFsLjAwNC0uMDAzIDMuODMgMy44MzFhLjgyNi44MjYgMCAxIDAgMS4xNjctMS4xNjl6TTUuNDk2IDkuODc4YTQuNDI2IDQuNDI2IDAgMCAxLTQuNC00LjQwNiA0LjM1IDQuMzUgMCAwIDEgNC4zNjgtNC4zNzQgNC40MjUgNC40MjUgMCAwIDEgNC40IDQuNDA2IDQuMzUgNC4zNSAwIDAgMS00LjM2OCA0LjM3NHoiCiAgICAgICAgZmlsbD0iIzhFOEU5MyIgZmlsbC1ydWxlPSJldmVub2RkIiAvPgo8L3N2Zz4K) center center no-repeat;
}
/* Formatted (Prettier 1.11.1): */
.search-icon {
background: url(
data:image/svg+xml;base64,
PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8cGF0aCBkPSJNMTMuNzQzIDEyLjU3NEw5LjkxIDguNzRhNS40MjUgNS40MjUgMCAwIDAgMS4wNS0zLjIzMkE1LjUzMiA1LjUzMiAwIDAgMCA1LjQ2IDAgNS40MzYgNS40MzYgMCAwIDAgMCA1LjQ2OGE1LjUzMiA1LjUzMiAwIDAgMCA1LjUgNS41MDggNS40MDggNS40MDggMCAwIDAgMy4yNDItMS4wNjFsLjAwNC0uMDAzIDMuODMgMy44MzFhLjgyNi44MjYgMCAxIDAgMS4xNjctMS4xNjl6TTUuNDk2IDkuODc4YTQuNDI2IDQuNDI2IDAgMCAxLTQuNC00LjQwNiA0LjM1IDQuMzUgMCAwIDEgNC4zNjgtNC4zNzQgNC40MjUgNC40MjUgMCAwIDEgNC40IDQuNDA2IDQuMzUgNC4zNSAwIDAgMS00LjM2OCA0LjM3NHoiCiAgICAgICAgZmlsbD0iIzhFOEU5MyIgZmlsbC1ydWxlPSJldmVub2RkIiAvPgo8L3N2Zz4K
)
center center no-repeat;
}
/* Formatted (Prettier 1.12.0): */
.search-icon {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8cGF0aCBkPSJNMTMuNzQzIDEyLjU3NEw5LjkxIDguNzRhNS40MjUgNS40MjUgMCAwIDAgMS4wNS0zLjIzMkE1LjUzMiA1LjUzMiAwIDAgMCA1LjQ2IDAgNS40MzYgNS40MzYgMCAwIDAgMCA1LjQ2OGE1LjUzMiA1LjUzMiAwIDAgMCA1LjUgNS41MDggNS40MDggNS40MDggMCAwIDAgMy4yNDItMS4wNjFsLjAwNC0uMDAzIDMuODMgMy44MzFhLjgyNi44MjYgMCAxIDAgMS4xNjctMS4xNjl6TTUuNDk2IDkuODc4YTQuNDI2IDQuNDI2IDAgMCAxLTQuNC00LjQwNiA0LjM1IDQuMzUgMCAwIDEgNC4zNjgtNC4zNzQgNC40MjUgNC40MjUgMCAwIDEgNC40IDQuNDA2IDQuMzUgNC4zNSAwIDAgMS00LjM2OCA0LjM3NHoiCiAgICAgICAgZmlsbD0iIzhFOEU5MyIgZmlsbC1ydWxlPSJldmVub2RkIiAvPgo8L3N2Zz4K)
center center no-repeat;
}
Prettier 1.11.0 was breaking code when inline comments appeared within SCSS lists or maps. This has been fixed in Prettier 1.12.0. Note: This formatting style is still not ideal, but this fixes the code breaking.
<!-- prettier-ignore -->// Input:
$my-list:
'foo', // Foo
'bar'; // Bar
$my-map: (
'foo': 1, // Foo
'bar': 2, // Bar
);
// Formatted (Prettier 1.11.1):
$my-list: "foo", / / Foo "bar"; // Bar
$my-map: (
"foo": 1,
/ / Foo "bar": 2,
/ / Bar
);
// Formatted (Prettier 1.12.0):
$my-list: "foo",
// Foo
"bar"; // Bar
$my-map: (
"foo": 1,
// Foo
"bar": 2,
// Bar
);
Prettier 1.11.1 was incorrectly lower-casing names of CSS variables exported from CSS modules. This would cause issues when attempting to import the variable from the module on the JavaScript side.
<!-- prettier-ignore -->/* Input: */
:export {
myColor: red;
}
/* Formatted (Prettier 1.11.1): */
:export {
mycolor: red;
}
This has been fixed in Prettier 1.12.0:
<!-- prettier-ignore -->/* Formatted (Prettier 1.12.0): */
:export {
myColor: red;
}
unicode-range (#4117 by @evilebottnawi)Prettier 1.11.1 was printing unicode-range rules incorrectly. This has been fixed in Prettier 1.12.0.
/* Input: */
@font-face {
unicode-range: U+00-FF;
}
/* Formatted (Prettier 1.11.1): */
@font-face {
unicode-range: U + 00-FF;
}
/* Formatted (Prettier 1.12.0): */
@font-face {
unicode-range: U+00-FF;
}
Prettier's team is continuing to work on our not-yet-production-ready HTML formatter. This release includes a fix where a comment at the top of a document (like an htmlhint comment) caused the document to not be formatted properly. This issue has been fixed.
else if (#4256 by @n8n8baby)Our handlebars formatter is also not yet ready for public consumption, but a fix was added during this release cycle so that else if blocks are printed correctly. Prettier 1.11.1 mistakenly converted them into ifs.
Prettier 1.11.1 did not handle self-closing style or script tags correctly in vue files; it would print things in an unexpected way. This has been fixed in Prettier 1.12.0.
<!-- prettier-ignore --><!-- Input: -->
<template>
<span :class="$style.root"><slot /></span>
</template>
<style src="./style.css" module />
<!-- Formatted (Prettier 1.11.1): -->
<template>
<span :class="$style.root"><slot /></span>
</template>
<style src="./style.css" module />
<template><span : class= "$style.root" ><slot / ></span> </template> <style src=
"./style.css" module / >;
<template>
<span :class="$style.root"><slot /></span>
</template>
<style src="./style.css" module />
<!-- Formatted (Prettier 1.12.0): -->
<template>
<span :class="$style.root"><slot /></span>
</template>
<style src="./style.css" module />
--range-start and --range-end can now be specified in the playground thanks to work by @JamesHenry. This will help the prettier community, because it streamlines the bug reporting process for bugs related to formatting a selection in the editor.
Prettier 1.11.1 was mistakenly outputting the contents of ignored files when the --debug-check flag was used. In Prettier 1.12.0, the contents of ignored files are no longer written to stdout.
To Prettier's amazing community of users, contributors, and maintainers, thank you! This is something that we can only build together ❤️