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
#5979 by @jwbay)
Stop breaking simple template literals (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}%`
)
);
#6127 by @duailibe)
Stop converting empty JSX elements to self-closing elements (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
#5947 by @jridgewell)
Fix closure compiler typecasts (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);
#6116 by @jridgewell)
Fix closure typecasts without spaces (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);
--quote-props=consistent
and objects had numbers or computed expressions as keys (#6119 and #6138 by @duailibe)
Prevent adding quotes when using 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: ""
};
#6130 by @duailibe)
Add parenthesis in JSX spread element with logical expressions (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 || {})} />;
#6086 by @evilebottnawi)
Correctly handle comments in empty arrow function expressions (// 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);
#6088 by @evilebottnawi)
Do not hug sequence expression in object properties (// Input
const a = {
someKey:
(longLongLongLongLongLongLongLongLongLongLongLongLongLongName, shortName)
};
// Output (Prettier stable)
const a = {
someKey: (longLongLongLongLongLongLongLongLongLongLongLongLongLongName,
shortName)
};
// Output (Prettier master)
const a = {
someKey:
(longLongLongLongLongLongLongLongLongLongLongLongLongLongName, shortName)
};
#6089 by @hongrich)
Add support for styled-jsx external styles (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;
}
`;
export default
declarations (#6133 by @duailibe)
Keep parenthesis around functions and classes in 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);
new
(#6148 by @bakkot)
Address parentheses bugs for edge cases with call and 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();
#6038 by @thorn0)
Fix nested embeds (JS in HTML in JS) (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>
`;
new
expressions (#6152 by @sosukesuzuki)
Keep necessary parentheses around bind expressions passed to 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)();
#6159 by @duailibe)
Prevent adding unnecessary parentheses around bind expressions in member expressions' properties (// Input
f[a::b];
// Output (Prettier stable)
f[(a::b)];
// Output (Prettier master);
f[a::b];
TypeScript
#6115 by @sosukesuzuki)
Keep trailing comma in TSX type parameters (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;
#6106 by @brainkim)
Don’t breakup call expressions when the last argument is an arrow function with a simple return type (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!");
});
#6131 by @sosukesuzuki)
Keep a pair of parentheses when there are extra pairs (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)[];
#6136 by @sosukesuzuki, #6140 by @thorn0, #6148 by @bakkot)
Keep necessary parentheses around non-null assertions (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())!();
#6146 by @sosukesuzuki)
Keep line breaks within mapped types (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];
};
--trailing-comma=all
(#6172 by @sosukesuzuki)
Add trailing comma on tuple types with 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
#6110 by @belochub)
Determine correctly the count of backticks in inline code (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!
#6178 by @GavinJoyce)
Avoid adding unwanted whitespace after components (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
#6129 by @duailibe)
Prettier now works in Atom again (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.