prettier/website/blog/2018-02-26-1.11.0.md

29 KiB

author authorURL title
Suchipi (@suchipi) https://github.com/suchipi Prettier 1.11: CSS fixes and new TypeScript feature support

This release features a ton of CSS formatting fixes as well as support for some new TypeScript features, in addition to some general bugfixes for other languages.

Since the last release, the Prettier website has gotten an all-new design thanks to @orta!

Facebook is 💯% Prettier

Another exciting announcement is that all the JavaScript files in the Facebook codebase have now been converted to Prettier! What's mind-blowing is that there hasn't been a concerted push to convert the codebase to Prettier, we just added the tooling in place and documentation on how to migrate a folder to Prettier and people just started converting their piece of the codebase.

In 8 months, 75% of the codebase was organically converted and last week we did a final push to convert the rest and enforce that every file from now on is using Prettier! It shows that Prettier is robust to support all the crazy edge cases you can imagine and also that it provides a lot of value given the crazy adoption rate.

Highlights

CSS/SCSS/Less

Our CSS formatting got a lot of love from @evilebottnawi during this release!

Format at-rules (#3828 by @evilebottnawi)

Previously, some at-rules (like @if and @include) were not formatted by Prettier and were instead printed as-is. They are now formatted:

// Before:
.selector {
  @include absolute($top: $long-variable-name, $right: $long-variable-name, $left: auto, $bottom: auto);
}

// After:
.selector {
  @include absolute(
    $top: $long-variable-name,
    $right: $long-variable-name,
    $left: auto,
    $bottom: auto
  );
}

Some popular PostCSS plugins like postcss-mixins were not working due to how Prettier was formatting CSS. These plugins are now respected:

// Before
$theme: blue;

a {
  @mixin $(theme) -colors;
}

// After
$theme: blue;

a {
  @mixin $(theme)-colors;
}

Support YAML front-matter block in SCSS (#3802 by @evilebottnawi)

Jekyll relies on YAML front-matter to detect SCSS files, but Prettier was removing it, which would break Jekyll sites when deployed. The YAML front-matter is now preserved, which preserves styling:

---
title: Title
description: Description
---

a {
  color: red;
}

TypeScript

Support definite assignment (!:) (#4020 by @ikatyang)

TypeScript 2.7 added a new feature called definite assignment that can be used in class property initializers. It informs TypeScript that even though a class property does not have an initializer, we can be sure that at runtime it will have a value, rather than undefined:

class MyComponent {
  ngModel!: ng.INgModelController;
}

Prettier 1.10.2 couldn't parse this syntax:

SyntaxError: '=' expected. (2:10)
  1 | class MyComponent {
> 2 |   ngModel!: ng.INgModelController;
    |          ^
  3 | }

But it is now supported in Prettier 1.11.0.

Support unique symbol (#3967 by @ikatyang)

TypeScript 2.7 also added a new unique symbol type:

interface SymbolConstructor {
  readonly iterator: unique symbol;
}

Prettier 1.10.2 couldn't parse this syntax:

SyntaxError: ';' expected. (2:29)
  1 | interface SymbolConstructor {
> 2 |   readonly iterator: unique symbol;
    |                             ^
  3 | }
  4 |

But it is now supported in Prettier 1.11.0.

Support condition types (#4006 by @Cryrivers)

TypeScript 2.8 will add support for conditional types, which look like ternaries but appear in a type position:

export type DeepReadonly<T> =
    T extends any[] ? DeepReadonlyArray<T[number]> :
    T extends object ? DeepReadonlyObject<T> :
    T;

Prettier 1.10.2 couldn't parse these:

SyntaxError: ';' expected. (2:7)
  1 | export type DeepReadonly<T> =
> 2 |     T extends any[] ? DeepReadonlyArray<T[number]> :
    |       ^
  3 |     T extends object ? DeepReadonlyObject<T> :
  4 |     T;

But this syntax is supported in Prettier 1.11.0.

JavaScript

Ternaries were indented incorrectly with --use-tabs (#3745 by @ikatyang)

Because tabs can be represented as different widths, Prettier was sometimes indenting ternaries incorrectly when using tabs. Now we calculate the indentation properly:

// Before:
const abc = props.something
	? xyz
	: {
			prop1: a,
			prop2: b,
			prop3: false,
		};

// After:
const abc = props.something
	? xyz
	: {
			prop1: a,
			prop2: b,
			prop3: false
	  };

Other Changes

CSS/SCSS/Less

Lists of lists now have cleaner formatting (#3930 by @evilebottnawi)

We weren't handling lists of lists very well in SCSS. Now we handle them better.

// Before:
$space-scale: (0, "0") (0.25, "0-25") (0.5, "0-5") (0.75, "0-75") (1, "1")
  (
    1.25,
    "1-25"
  ) (1.5, "1-5") (1.75, "1-75") (2, "2") (2.25, "2-25") (2.5, "2-5")
  (
    2.75,
    "2-75"
  ) (3, "3") (3.25, "3-25") (3.5, "3-5") (3.75, "3-75") (4, "4");

// After:
$space-scale: (0, "0") (0.25, "0-25") (0.5, "0-5") (0.75, "0-75") (1, "1")
  (1.25, "1-25") (1.5, "1-5") (1.75, "1-75") (2, "2") (2.25, "2-25")
  (2.5, "2-5") (2.75, "2-75") (3, "3") (3.25, "3-25") (3.5, "3-5")
  (3.75, "3-75") (4, "4");

Preserve comment in font-face declaration (#3906 by @evilebottnawi)

Previously, if you had code like this:

@font-face {
  font-family: "Prettier";
  src: local("Prettier"), /* Local */
    url("http://prettier.com/font.woff") /* Network*/
}

Then the "Local" comment was removed by Prettier:

@font-face {
  font-family: "Prettier";
  src: local("Prettier"), url("http://prettier.com/font.woff"); /* Network*/
}

It is now preserved:

@font-face {
  font-family: "Prettier";
  src: local("Prettier"), /* Local */ url("http://prettier.com/font.woff"); /* Network*/
}

CSS indentation no longer indents with 3 spaces when line starts with a paren (#3930 by @evilebottnawi)

If a line of CSS was to be indented and the first character in that line was a paren, the CSS was mistakenly indented with 3 spaces instead of the expected 2. Now it's indented with 2 spaces.

// Before:
$longVariable: (
   (mobile $mobile) (tablet $tablet) (desktop $desktop) (wide $wide)
);

// After:
$longVariable: (
  (mobile $mobile) (tablet $tablet) (desktop $desktop) (wide $wide)
);

Extra space is no longer added inside maps (#3814 by @evilebottnawi)

Prettier was mistakenly adding spaces inside SCSS maps. They are no longer printed.

// Before:
$map: map-merge($map,  ($key: $value));

// After:
$map: map-merge($map, ($key: $value));

SCSS comments in selector lists no longer break formatting (#3909 by @evilebottnawi)

Prettier was formatting trailing SCSS comments in CSS selector lists incorrectly, breaking code:

// Before formatting:
.field {
  &[data-field-id="1"], // Name
  &[data-field-id="2"], // Email
  &[data-field-id="3"], // Postal Code
  {
    background: green;
  }
}

// After formatting (Prettier 1.10.2):
.field {
  &[data-field-id="1"],
  // Name &[data-field-id="2"],
  // Email &[data-field-id="3"] {
    background: green;
  }
}

Prettier now handles these comments correctly:

// After formatting (Prettier 1.11.0):
.field {
  &[data-field-id="1"], // Name
  &[data-field-id="2"], // Email
  &[data-field-id="3"], // Postal Code
 {
    background: green;
  }
}

Comma no longer added after @import url (#3770 by @evilebottnawi)

Prettier was mistakenly adding a comma after @import urls. This is no longer added:

/* Before */
@import url("responsive/gt768.css"), screen and (min-width: 768px);

/* After */
@import url("responsive/gt768.css") screen and (min-width: 768px);

Handle !default directive properly (#3724 by @evilebottnawi)

Prettier was printing the !default directive in an odd way:

$theme-checkbox-colors: (
    default: $theme-color-border,
    checked: $theme-color-checked,
    disabled: $theme-color-disabled,
    disabled-font: $theme-color-font-secondary
  )
  !default;

It's now handled properly:

$theme-checkbox-colors: (
  default: $theme-color-border,
  checked: $theme-color-checked,
  disabled: $theme-color-disabled,
  disabled-font: $theme-color-font-secondary
) !default;

Don't format contents of @warn and @error directives (#3769 by @evilebottnawi)

SCSS has a feature that lets you output some text at build-time using @warn or @error:

// Unformatted code:
@if ($error) {
  @error 'An error occurred: (#{$error}).';
}

Unfortunately, Prettier was treating these directives as media queries, formatting their contents in unexpected ways (in this example, a space is added before the period):

// Formatted code (Prettier 1.10.2):
@if ($error) {
  @error 'error (#{$error}) .';
}

Prettier now handles these directives correctly, and will not change the contents of the string:

// Formatted code (Prettier 1.11.0):
@if ($error) {
  @error "error (#{$error}).";
}

Don't remove semicolon in Less ruleset declaration (#3841 by @evilebottnawi)

Prettier was mistakenly removing semicolons after Less ruleset declarations, which needed to stay, or else compilation errors would occur. They are now preserved:

// Before:
@detached-ruleset: {
  background: red;
}

// After:
@detached-ruleset: {
  background: red;
};

Don't add newline to empty CSS file (#3723 by @hudochenkov)

Prettier was previously adding an end-of-file newline to CSS files. We didn't do this for JS files, so we decided to make this behavior consistent in CSS so that it wouldn't introduce surprising source control changes when adding Prettier to a project.

Ignore media params with SCSS interpolation (#3801 by @evilebottnawi)

Prettier was mistakenly breaking code when a media query contained SCSS interpolation. It is now preserved:

// Unformatted code:
$sm-only: '(min-width: 768px) and (max-width: 991px)';
$lg-and-up: '(min-width: 1200px)';

@media screen and #{$sm-only, $lg-and-up} {
    color: #000;
}

// Formatted code (Prettier 1.10.2):
@media screen and,  {
	color: #000;
}

// Formatted code (Prettier 1.11.0):
$sm-only: "(min-width: 768px) and (max-width: 991px)";
$lg-and-up: "(min-width: 1200px)";

@media screen and #{$sm-only, $lg-and-up} {
  color: #000;
}

Don't print two spaces between selector operator and opening bracket (#3738 by @evilebottnawi)

Prettier was mistakenly printing an extra space when a CSS selector ended in an operator (a feature supported by SCSS). This has been fixed:

// Unformatted code:
.this > .ends > .with > .an > .operator > {
  // content
}

// Formatted code (Prettier 1.10.2):
.this > .ends > .with > .an > .operator >  {
  // content
}

// Formatted code (Prettier 1.11.0):
.this > .ends > .with > .an > .operator > {
  // content
}

Don't change case of SCSS function names (#3768 by @evilebottnawi)

Prettier was mistakenly lowercasing SCSS function names in certain cases. This has been fixed.

// Unformatted code:
@include breakpoint (getBp(md)) {
  &:nth-child(2n + 3) {
    clear: both;
  }
}

// Formatted code (Prettier 1.10.2):
@include breakpoint (getbp(md)) {
  &:nth-child(2n + 3) {
    clear: both;
  }
}

// Formatted code (Prettier 1.11.0):
@include breakpoint(getBp(md)) {
  &:nth-child(2n + 3) {
    clear: both;
  }
}

Keep space around Vue deep selector >>> (#3792 by @evilebottnawi)

Prettier was mistakenly stripping spaces around Vue's deep selector:

<!-- Unformatted code: -->
<style scoped>
  .box >>> .child-component {
    font-size: 24px;
  }
</style>

<!-- Formatted code (Prettier 1.10.2): -->
<style scoped>
  .box>>>.child-component {
    font-size: 24px;
  }
</style>

<!-- Formatted code (Prettier 1.11.0): -->
<style scoped>
.box >>> .child-component {
  font-size: 24px;
}
</style>

Fix @nest at-rule (#3975 by @evilebottnawi)

Prettier was mistakenly adding spaces around the & character in selectors passed to @nest, which changed which selector the rule compiled into. This has been fixed:

// Unformatted code:
.title {
  @nest :global(h1)& {
    background: red;
  }
}

// Formatted code (Prettier 1.10.2):
.title {
  @nest :global(h1) & {
    background: red;
  }
}

// Formatted code (Prettier 1.11.0):
.title {
  @nest :global(h1)& {
    background: red;
  }
}

Format progid:DXImageTransform.Microsoft.gradient as-is (#4028 by @evilebottnawi)

In Prettier 1.10.2, we had a lot of logic to handle formatting of Microsoft-browser-specific filter values, but they still weren't formatting very well. Since they are non-standard and infrequently used, we've decided to print them as-is without attempting to format them.

Don't lowercase nesting selector (#4048 by @evilebottnawi)

In Prettier 1.10.2, we were incorrectly lower-casing nesting SCSS selectors:

// Unformatted code:
.foo {
  &-1Bar {
  }
}

// Formatted code: (Prettier 1.10.2):
.foo {
  &-1bar {
  }
}

This has been fixed in Prettier 1.11.0:

// Formatted code: (Prettier 1.11.0):
.foo {
  &-1Bar {
  }
}

JavaScript

Don't print odd-looking parens around return argument with comment (#3665 by @duailibe)

Prettier was printing parens around the argument to a return statement in an odd way when the argument contained a comment. These parens are now formatted better.

// Unformatted code:
func1(function() {
  return func2
      //comment
      .bar();
});

// Formatted code (Prettier 1.10.2):
func1(function() {
  return (func2
      //comment
      .bar() );
});

// Formatted code (Prettier 1.11.0):
func1(function() {
  return (
    func2
      //comment
      .bar()
  );
});

Respect 0-indent markdown-in-js (#3676 by @ikatyang)

Prettier's markdown-in-js formatting (triggered by using a template literal tag named md was inserting indentation):

// Unformatted code
md`
This is some markdown
`

// Formatted code (Prettier 1.10.2)
md`
  This is some markdown
`;

This was desired and acceptable behavior for many markdown template tag functions, such as react-markings, but it broke some other in-house markdown formatters.

Prettier 1.11.0 will now respect the indentation level you set in your markdown, so users of template tag functions like the one provided by react-markings can continue to indent their code, and users of other template tag functions which do not support indentation can choose not to.

Format AMD define calls like CJS require calls (#3830 by @salemhilal)

When using AMD modules, one pattern is to use define to specify the dependencies of an anonymous module like so:

define([
  "jquery",
  "common/global.context",
  "common/log.event",
  "some_project/square",
  "some_project/rectangle",
  "some_project/triangle",
  "some_project/circle",
  "some_project/star"
], function($, Context, EventLogger, Square, Rectangle, Triangle, Circle, Star) {
  console.log("some code");
});

Prettier 1.10.2 was breaking this onto multiple lines, which introduced a lot of top-level indentation:

define(
  [
    "jquery",
    "common/global.context",
    "common/log.event",
    "some_project/square",
    "some_project/rectangle",
    "some_project/triangle",
    "some_project/circle",
    "some_project/star"
  ],
  function($, Context, EventLogger, Square, Rectangle, Triangle, Circle, Star) {
    console.log("some code");
  }
);

Prettier 1.11.0 will now make the array and function expression "hug", which decreases the indentation level:

define([
  "jquery",
  "common/global.context",
  "common/log.event",
  "some_project/square",
  "some_project/rectangle",
  "some_project/triangle",
  "some_project/circle",
  "some_project/star"
], function(
  $,
  Context,
  EventLogger,
  Square,
  Rectangle,
  Triangle,
  Circle,
  Star
) {
  console.log("some code");
});

Format QUnit's skip like test (#3735 by @tmquinn)

Prettier was special-casing formatting for describe, it, and test to improve formatting in tests based on user expectations and requests. However, we were not formatting QUnit's skip method using the same logic, which led to mixed formatting when switching a test between test and skip:

// Unformatted code
test("this is a really long description of some test I want to go here", function (assert) {
  assert("something");
});

skip("this is a really long description of some test I want to go here", function (assert) {
  assert("something");
});

// Formatted code (Prettier 1.10.2):
test("this is a really long description of some test I want to go here", function(assert) {
  assert("something");
});

skip(
  "this is a really long description of some test I want to go here",
  function(assert) {
    assert("something");
  }
);

We now treat skip the same as describe, it, and test, which makes QUnit tests look more uniform:

// Formatted code (Prettier 1.11.0):
test("this is a really long description of some test I want to go here", function(assert) {
  assert("something");
});

skip("this is a really long description of some test I want to go here", function(assert) {
  assert("something");
});

Break JSX element if a string literal prop has a newline (#4011 by @duailibe)

Newline characters are allowed within a JSX string literal according to the JSX spec, but Prettier was not treating a JSX element as multi-line when one of its attribute values was a string containing a newline character. Prettier will now treat these elements as multi-line as expected:

// Unformatted code:
<path d="M4.765 16.829l3.069-2.946 5.813 5.748
  11.33-11.232 3.006 3.18-14.36 14.080z"
/>;

// Formatted code (Prettier 1.10.2):
<path d="M4.765 16.829l3.069-2.946 5.813 5.748
  11.33-11.232 3.006 3.18-14.36 14.080z" />;

// Formatted code (Prettier 1.11.0):
<path
  d="M4.765 16.829l3.069-2.946 5.813 5.748
  11.33-11.232 3.006 3.18-14.36 14.080z"
/>;

Support JSX children spread with flow parser (#3899 by @vjeux)

Using a spread operator in a JSX children expression container position caused a parsing error in Prettier 1.10.2 when using the flow parser:

<JSX>
  {...edges}
</JSX>
SyntaxError: Unexpected token ... (2:4)
  1 | <JSX>
> 2 |   {...edges}
    |    ^^^
  3 | </JSX>

In Prettier 1.11.0, this syntax is supported with the flow parser.

Fix error when printing flow maybe object return type (#3948 by @azz)

In Prettier 1.10.2, this code caused an error to be thrown:

function getScaledData({x}): ?{foo: number} {}

It has been fixed in Prettier 1.11.0.

--insert-pragma no longer removes duplicate pragmas (#3947 by @azz)

Using --insert-pragma on code with duplicate pragmas was removing all but one of the duplicates. This has been fixed:

// Unformatted code:
/**
 * @x 1
 * @x 2
 */

// Formatted code (Prettier 1.10.2):
/**
 * @format
 * @x 2
 */

// Formatted code (Prettier 1.11.0):
/**
 * @format
 * @x 1
 * @x 2
 */

Wrap flow-typecasted ternaries in parens (#3940 by @j-f1)

To improve code clarity, typecast ternaries will now be wrapped in parens:

// Unformatted code:
const foo = ((1?2:3): number);

// Formatted code (Prettier 1.10.2):
const foo = (1 ? 2 : 3: number);

// Formatted code (Prettier 1.11.0):
const foo = ((1 ? 2 : 3): number);

Fix cases with missing semi when printing DeclareExportDeclaration (#3979 by @existentialism)

Semicolons were being mistakenly removed from declare export default statements in flow library definition files. This has been fixed.

TypeScript

Don't remove parens from (void 0)! (#3989 by @azz)

Prettier was mistakenly removing parens from (void 0)!, which changed the AST of the program. This has been fixed.

Properly chain when there is a TSNonNullExpression (#4005 by @ericanderson)

Prettier was not using its chaining formatting style when the chain included a TypeScript ! non-null expression. This has been fixed:

// Unformatted code:
this.tokenLoads.get(locator).get(start).push({});

this.tokenLoads.get(locator)!.get(start).push({});

// Formatted code (Prettier 1.10.2):
this.tokenLoads
  .get(locator)
  .get(start)
  .push({});

this.tokenLoads.get(locator)!.get(start).push({});

// Formatted code (Prettier 1.11.0):
this.tokenLoads
  .get(locator)
  .get(start)
  .push({});

this.tokenLoads
  .get(locator)!
  .get(start)
  .push({});

Markdown

Heading after list item gets merged into list (#3780 by @ikatyang)

Prettier was mistakenly merging a heading beneath a list item into the list. Now it is treated as a header:

<!-- Unformatted code -->
* Something
### Some heading

<!-- Formatted code (Prettier 1.10.2) -->
* Something
  ### Some heading

<!-- Formatted code (Prettier 1.11.0) -->
* Something

### Some heading

Links whose URL contained HTML entities were mistakenly being changed when run through Prettier. They are now preserved.

<!-- Unformatted code -->
[Test](http://localhost:8080/test?language=DE&currency=EUR)

<!-- Formatted code (Prettier 1.10.2) -->
[Test](http://localhost:8080/test?language=DE¤cy=EUR)

<!-- Formatted code (Prettier 1.11.0) -->
[Test](http://localhost:8080/test?language=DE&currency=EUR)

Fix indentation of template strings within code blocks (#3676 by @ikatyang)

Indentation of JS tagged template string content within markdown code blocks was being calculated incorrectly:

<!-- Unformatted code: -->
- 1
  - 2
    - 3
      ```js
      something`
      asd

      asd

      asd
      `
      ```

<!-- Formatted code (Prettier 1.10.2): -->
* 1

  * 2

    * 3

      ```js
      something`
asd

asd

asd
`;
      ```

It has been fixed in Prettier 1.11.0:

<!-- Formatted code (Prettier 1.11.0): -->
* 1

  * 2

    * 3

      ```js
      something`
      asd

      asd

      asd
      `;
      ```

Print multiline content correctly in footnoteDefinition (#3787 by @ikatyang)

Prettier was mistakenly using the incorrect level of indentation when printing a footnote that contained a code block. This has been fixed:

<!-- Unformatted code: -->
Some text.[^fn]

[^fn]: Here is a footnote which includes code.

    ```rs
    fn main() {
        println!("this is some Rust!");
    }
    ```

<!-- Formatted code (Prettier 1.10.2): -->
Some text.[^fn]

[^fn]: Here is a footnote which includes code.

```rs
fn main() {
    println!("this is some Rust!");
}
```

<!-- Formatted code (Prettier 1.11.0): -->
Some text.[^fn]

[^fn]: Here is a footnote which includes code.

  ```rs
  fn main() {
      println!("this is some Rust!");
  }
  ```

Respect tabWidth for list items (#3990 by @ikatyang)

We've discovered that CommonMark diverges from the original Markdown syntax for code blocks in list items. This leads to scenarios where indented code-blocks in Markdown where being rendered as regular paragraphs. This change uses the tabWidth option to determine how much indentation to use in list items. Have a read through #3459 if you're interested in the details.

<!-- before -->
1. Change to your home directory:

   cd

<!-- after -->
1. Change to your home directory:

        cd

This change should also improve indentation in text editors:

API

Support options in plugins (#3775 by @ikatyang)

As part of fleshing out our beta plugin API for community-made language plugins, we have added support for plugins to define their own options!

Plugin options can now be printed in help:

prettier --plugin @prettier/plugin-python --help

Likewise, plugin options can be specified on the command-line:

prettier --plugin my-cool-prettier-plugin --my-custom-option

And plugin options can also be defined in .prettierrc:

{ "plugins": ["foo-plugin"], "fooOption": "bar" }

Don't allow kebab-cased options in config files (#3622 by @ikatyang)

Prettier was mistakenly allowing kebab-case variations of options in .prettierrc files:

{ "print-width": 100 }

This was not intended to be allowed, and has been reverted (in this case, you would need to use printWidth).

Configuration

Respect EditorConfig when --config is passed (#3992 by @josephfrazier)

This is a minor change to the the way .editorconfig files are handled. Previously when --config was provided, .editorconfig was ignored.


Thanks to all of Prettier's contributors and the community for making Prettier a successful and productive open-source project! We couldn't do it without everyone ❤️