prettier/website/blog/2019-06-06-1.18.0.md

15 KiB
Raw Permalink Blame History

author authorURL title
Lucas Duailibe (@duailibe) https://github.com/duailibe Prettier 1.18: Lots of fixes and OpenCollective

This release doesn't include shiny new features, but has lots of fixes for JavaScript, specially JSX and template literals, TypeScript and Markdown.

It's also a good opportunity to remind that Prettier is now accepting donations! If you enjoy Prettier and would like to support our work, head to our OpenCollective.

Highlights

JavaScript

Stop breaking simple template literals (#5979 by @jwbay)

This is one of the Prettier parts that get a lot of change requests: breaking simple expressions inside template literals. Previously Prettier would break the expressions in multiple lines if the whole literal exceeded the print width. Now, we'll prevent breaking if the expression is simple.

This is an improvement to what we had before, but there's still work to be done in this area.

// Input
console.log(chalk.white(`Covered Lines below threshold: ${coverageSettings.lines}%. Actual: ${coverageSummary.total.lines.pct}%`))

// Output (Prettier stable)
console.log(
  chalk.white(
    `Covered Lines below threshold: ${coverageSettings.lines}%. Actual: ${
      coverageSummary.total.lines.pct
    }%`
  )
);

// Output (Prettier master)
console.log(
  chalk.white(
    `Covered Lines below threshold: ${coverageSettings.lines}%. Actual: ${coverageSummary.total.lines.pct}%`
  )
);

Stop converting empty JSX elements to self-closing elements (#6127 by @duailibe)

Prettier has always converted empty JSX elements (<div></div>) to self-closing elements (<div />) because those are equivalent.

We have received feedback that during development, one would like to type the opening and closing tags and leave them to add the children later, but Prettier would convert it to a self-closing element, forcing the developer to manually convert them back. This has changed in this release.

// Input
function Foo() {
  return <div></div>;
}

// Output (Prettier stable)
function Foo() {
  return <div />;
}

// Output (Prettier master)
function Foo() {
  return <div></div>;
}

Other changes

JavaScript

Fix closure compiler typecasts (#5947 by @jridgewell)

If a closing parenthesis follows after a typecast in an inner expression, the typecast would wrap everything to that following parenthesis.

// Input
test(/** @type {!Array} */(arrOrString).length);
test(/** @type {!Array} */((arrOrString)).length + 1);
// Output (Prettier stable)
test(/** @type {!Array} */ (arrOrString.length));
test(/** @type {!Array} */ (arrOrString.length + 1));
// Output (Prettier master)
test(/** @type {!Array} */ (arrOrString).length);
test(/** @type {!Array} */ (arrOrString).length + 1);

Fix closure typecasts without spaces (#6116 by @jridgewell)

Previously, a space was required between the @type and opening { of a closure typecast, or else the enclosing parenthesis would be removed. Closure itself does not require a space.

// Input
const v = /** @type{string} */(value);

// Output (Prettier stable)
const v = /** @type{string} */ value;

// Output (prettier master)
const v = /** @type{string} */ (value);

Prevent adding quotes when using --quote-props=consistent and objects had numbers or computed expressions as keys (#6119 and #6138 by @duailibe)

Previously, Prettier added unnecessary quotes to keys of an object, or properties and methods of classes, if there was at least one computed key with a "complex" expression (e.g. a member expression) or a numeric literal.

// Input
const obj = {
  foo: "",
  [foo.bar]: "",
};

const other = {
  foo: "",
  1: ""
};

// Output (Prettier stable)
const obj = {
  "foo": "",
  [foo.bar]: "",
};

const other = {
  "foo": "",
  1: ""
};

// Output (Prettier master)
const obj = {
  foo: "",
  [foo.bar]: "",
};

const other = {
  foo: "",
  1: ""
};

Add parenthesis in JSX spread element with logical expressions (#6130 by @duailibe)

Previously, Prettier didn't add parenthesis in JSX spread elements because they aren't necessary, but for the sake of consistency with spread operator in objects and arrays, we'll add to JSX as well.

// Input
<Component {...(props || {})} />;

// Output (Prettier stable)
<Component {...props || {}} />;

// Output (Prettier master)
<Component {...(props || {})} />;

Correctly handle comments in empty arrow function expressions (#6086 by @evilebottnawi)

// Input
const fn = (/*event, data*/) => doSomething(anything);

// Output (Prettier stable)
const fn = () => /*event, data*/ doSomething(anything);

// Output (Prettier master)
const fn = (/*event, data*/) => doSomething(anything);

Do not hug sequence expression in object properties (#6088 by @evilebottnawi)

// Input
const a = {
  someKey:
    (longLongLongLongLongLongLongLongLongLongLongLongLongLongName, shortName)
};

// Output (Prettier stable)
const a = {
  someKey: (longLongLongLongLongLongLongLongLongLongLongLongLongLongName,
  shortName)
};

// Output (Prettier master)
const a = {
  someKey:
    (longLongLongLongLongLongLongLongLongLongLongLongLongLongName, shortName)
};

Add support for styled-jsx external styles (#6089 by @hongrich)

Add support for 2 external styles tags in styled-jsx/css: css.global, and css.resolve. https://github.com/zeit/styled-jsx/#external-css-and-styles-outside-of-the-component

The css template tag is already supported by Prettier.

// Input
const styles = css.resolve`
.box {background:black;
}`;

// Output (Prettier stable)
const styles = css.resolve`
.box {background:black;
}`;

// Output (prettier master)
const styles = css.resolve`
  .box {
    background: black;
  }
`;

Keep parenthesis around functions and classes in export default declarations (#6133 by @duailibe)

Prettier was removing parenthesis from some expressions in export default, but if those are complex expressions that start with function or class, the parenthesis are required.

See below some practical examples, including one affecting TypeScript.

// Input
export default (function log() {}).toString();
export default (function log() {} as typeof console.log);

// Output (Prettier stable)
export default function log() {}.toString();
export default function log() {} as typeof console.log; // syntax error

// Output (Prettier master)
export default (function log() {}).toString();
export default (function log() {} as typeof console.log);

Address parentheses bugs for edge cases with call and new (#6148 by @bakkot)

Adding all and only the necessary parentheses when mixing new with function calls is tricky. This change fixes two issues where necessary parentheses were omitted and one when redundant parentheses were added.

// Input
new (x()``.y)();
new (x()!.y)();
new e[f().x].y()

// Output (Prettier stable)
new x()``.y();
new x()!.y();
new e[(f()).x].y();

// Output (Prettier master)
new (x())``.y();
new (x())!.y();
new e[f().x].y();

Fix nested embeds (JS in HTML in JS) (#6038 by @thorn0)

Previously, if JS code embedded in HTML (via <script>) embedded in JS (via a template literal) contained template literals, the inner JS was not formatted.

// Input
const html = /* HTML */ `<script>var a=\`\`</script>`;

// Output (Prettier stable)
// SyntaxError: Expecting Unicode escape sequence \uXXXX (1:8)

// Output (Prettier master)
const html = /* HTML */ `
  <script>
    var a = \`\`;
  </script>
`;

Keep necessary parentheses around bind expressions passed to new expressions (#6152 by @sosukesuzuki)

Previously, Prettier removed necessary parentheses around a bind expression if it was passed to a new expression.

// Input
new (a::b)();

// Output (Prettier stable)
new a::b();

// Output (Prettier master)
new (a::b)();

Prevent adding unnecessary parentheses around bind expressions in member expressions' properties (#6159 by @duailibe)

// Input
f[a::b];

// Output (Prettier stable)
f[(a::b)];

// Output (Prettier master);
f[a::b];

TypeScript

Keep trailing comma in TSX type parameters (#6115 by @sosukesuzuki)

Previously, a trailing comma after single type parameter in arrow function was cleaned up. The formatted result is valid as TS, but is invalid as TSX. This is now fixed in 1.19.

// Input
type G<T> = any;
const myFunc = <T,>(arg1: G<T>) => false;

// Output (Prettier stable)
type G<T> = any;
const myFunc = <T>(arg1: G<T>) => false;

// Output (prettier master)
type G<T> = any;
const myFunc = <T,>(arg1: G<T>) => false;

Dont breakup call expressions when the last argument is an arrow function with a simple return type (#6106 by @brainkim)

Fixes an edge case where we were splitting up call expressions containing arrow functions with simple return types.

app.get("/", (req, res): void => {
  res.send("Hello World!");
});

// Output (Prettier stable)
app.get(
  "/",
  (req, res): void => {
    res.send("Hello World!");
  },
);

// Output (Prettier master)
app.get("/", (req, res): void => {
  res.send("Hello World!");
});

Keep a pair of parentheses when there are extra pairs (#6131 by @sosukesuzuki)

Previously, Prettier removed necessary parentheses when trying to remove unnecessary parentheses, in TypeScript.

// Input
type G = ((keyof T))[];

// Output (Prettier stable)
type G = keyof T[];

// Output (prettier master)
type G = (keyof T)[];

Keep necessary parentheses around non-null assertions (#6136 by @sosukesuzuki, #6140 by @thorn0, #6148 by @bakkot)

Previously, Prettier removed necessary parentheses around non-null assertions if the result of the assertion expression was called as a constructor.

// Input
const b = new (c()!)();

// Output (Prettier stable)
const b = new c()!();

// Output (Prettier master)
const b = new (c())!();

Keep line breaks within mapped types (#6146 by @sosukesuzuki)

Previously, Prettier removed line breaks within mapped types. To make it similar to how we treat object literals, we will keep the line breaks if they existed in the source.

// Input
type A<T> = {
  readonly [P in keyof T]: T[P];
};

// Output (Prettier stable)
type A<T> = { readonly [P in keyof T]: T[P] };

// Output (Prettier master)
type A<T> = {
  readonly [P in keyof T]: T[P];
};

Add trailing comma on tuple types with --trailing-comma=all (#6172 by @sosukesuzuki)

TypeScript supports a trailing comma on tuple types since version 3.3.

// Input
export type Foo = [
  number,
  number, // comment
];

// Output (Prettier stable)
export type Foo = [
  number,
  number // comment
];

// Output (Prettier master);
export type Foo = [
  number,
  number, // comment
];

Markdown

Determine correctly the count of backticks in inline code (#6110 by @belochub)

By the CommonMark spec, it is required to 'choose a string of n backtick characters as delimiters, where the code does not contain any strings of exactly n backtick characters.'

This changes the method of finding the required count of backticks from using 2 backticks, when there is a backtick string of length 1 inside the inline code block, and using 1 backtick in all other cases, to finding a minimum length backtick string that can correctly be used as a delimiter.

<!-- Input -->
``` 3 ``22`` `1` ```

`` 2 ```123``` `1` ``

<!-- Output (Prettier stable) -->
` 3 ``22`` `1` `

` 2 ```123``` `1` `

<!-- Output (Prettier master) -->
``` 3 ``22`` `1` ```

`` 2 ```123``` `1` ``

Handlebars

While the Handlebars support is still in beta, @GavinJoyce is putting out some fixes so we can finally get to a stable release!

Avoid adding unwanted whitespace after components (#6178 by @GavinJoyce)

Previously, Prettier added a space before /> and a line break after, even when at the start of a line. Now, that extra space and line break is no longer present.

// Input
<div>
  <UserGreeting
    @aVeryLongArgumentNameThatIsStillGoing={{@alsoAVeryLongArgument}}
  />
</div>

// Output (Prettier stable)
<div>
  <UserGreeting
    @aVeryLongArgumentNameThatIsStillGoing={{@alsoAVeryLongArgument}}
   />

</div>

// Output (Prettier master)
<div>
  <UserGreeting
    @aVeryLongArgumentNameThatIsStillGoing={{@alsoAVeryLongArgument}}
  />
</div>

API

Prettier now works in Atom again (#6129 by @duailibe)

Atom has a security feature where code containing eval is not allowed to be run. One of Prettier's dependencies uses eval to prevent bundlers from including debug code. We've now made sure that this eval does not end up in the code we ship to npm, making Prettier play nice with Atom again.