Closed greenkeeper[bot] closed 6 years ago
Merging #190 into master will not change coverage. The diff coverage is
n/a
.
@@ Coverage Diff @@
## master #190 +/- ##
=======================================
Coverage 92.94% 92.94%
=======================================
Files 9 9
Lines 241 241
=======================================
Hits 224 224
Misses 17 17
Continue to review full report at Codecov.
Legend - Click here to learn more
Δ = absolute <relative> (impact)
,ø = not affected
,? = missing data
Powered by Codecov. Last update a16058f...915bb91. Read the comment docs.
Update to this version instead 🚀
I want to give a special shout out to @azz who has been maintaining the repository and implementing a bunch of the changes in this release as I had less time to devote to prettier due to vacation and switching team :)
Since the very first release of prettier, people have asked for a .prettierrc
file. We've been trying to have as few options as possible and tried to avoid being one more .dotfile
that you have to have when starting a new project.
But, the truth is, we need to have some way to configure prettier that can be kept in sync with all the integrations. By not having one, we pushed the problem to them and saw a bunch of incompatible ways of handling the problem. So now, it's handled by prettier itself.
// .prettierrc
{
"trailingComma": "es5",
"singleQuote": true
}
For more information on configuration file support, see the README.
Along with telling what configuration to use, you can write a file .prettierignore
to tell which files not to convert.
# .prettierignore
dist/
package.json
The last big friction point from people trying to adopt prettier was around how JSX was being printed. We went through all the issues that were raised and made a bunch of changes:
// Before
const Component = props =>
<div>
Hello {props.name}!
</div>;
// After
const Component = props => (
<div>
Hello {props.name}!
</div>
);
// Before
<div>
{props.isVisible
? <BaseForm
url="/auth/google"
method="GET"
/>
: <Placeholder />}
</div>;
// After
<div>
{props.isVisible ? (
<BaseForm
url="/auth/google"
method="GET"
/>
) : (
<Placeholder />
)}
</div>
// Before
<div>
{props.isVisible &&
<BaseForm
url="/auth/google"
method="GET"
/>}
</div>;
// After
<div>
{props.isVisible && (
<BaseForm
url="/auth/google"
method="GET"
/>
)}
</div>
Hopefully this is going to be more in line with how the majority of the community is writing JSX and we can have prettier be used in more place ;)
With JSX, we started by respecting a lot of line breaks that were in the original source. This had the advantage of doing fewer changes to your codebase but chipped away the value of a consistent pretty printer as the same semantic code could be written in two ways.
During each new release we've tightened this and made decisions around how to always print a piece of code. The latest of those is what happens if there's a single child in a JSX object, we're now always going to inline it.
// Before
return (
<div>
{this.props.test}
</div>
);
return <div>{this.props.test}</div>;
// After
return <div>{this.props.test}</div>;
return <div>{this.props.test}</div>;
Leading JSX empty spaces are now on their own line. It looked weird to have them before a tag as it "indented" it differently compared to the rest.
// Before
<span className="d1">
{' '}<a
href="https://github.schibsted.io/finn/troika"
className="link"
/>
</span>
// After
<span className="d1">
{' '}
<a
href="https://github.schibsted.io/finn/troika"
className="link"
/>
</span>
We used to use a strict JSON parser that would throw if there was a comment or a trailing comma. This was inconvenient as many JSON files in practice are parsed using JavaScript or json5 that are not as strict. Now, we have relaxed this and are using the JavaScript parser to parse and print JSON. This means that comments will be maintained if there were some.
Note that this is purely additive, if your original file was JSON compliant, it will keep printing a valid JSON.
// Before
Syntax error
// After
{ /* some comment */ "a": 1 }
Parenthesis are a hot topic because they are not part of the AST, so prettier ignores all the ones you are putting and re-creating them from scratch. We went through all the things that people reported and came up with a few edge cases that were very confusing when comparisons were chained and %
was mixed with *
or /
.
One thing that we are not changing is the fact that we remove extra parenthesis around combinations of basic arithmetic operators: +-*/
.
// Before
x !== y === z;
x * y % z;
// After
(x !== y) === z;
(x * y) % z;
It's useful to be able to ignore pieces of JSX, it's now possible to add a comment inside of a JSX expression to ignore the formatting of the next element.
// Before
<Component>
{/*prettier-ignore*/}
<span ugly format="" />
</Component>
// Before
<Component>
{/*prettier-ignore*/}
<span ugly format='' />
</Component>
In order to support some edge cases, in the internals, we have the ability to avoid printing comments in a generic way and print them in the call site instead. It turns out that when we used prettier-ignore
, we didn't print the comments at all! This is now fixed.
// Before
push(
<td> :)
</td>,
);
// After
push(
// prettier-ignore
<td> :)
</td>,
);
It took 6 months for someone to report that do-while were broken when the while condition is multi-line, it confirms my hunch that this construct is not widely used in practice.
// Before
do {} while (
someVeryLongFunc(
someVeryLongArgA,
someVeryLongArgB,
someVeryLongArgC
)
);
// After
do {} while (
someVeryLongFunc(
someVeryLongArgA,
someVeryLongArgB,
someVeryLongArgC
)
);
Another underused feature of JavaScript is sequence expressions. We used to do a bad job at printing them when they would go multi-line, this has been corrected :)
// Before
(a = b ? c : "lllllllllllllllllllllll"), (a = b
? c
: "lllllllllllllllllllllll"), (a = b ? c : "lllllllllllllllllllllll"), (a = b
? c
: "lllllllllllllllllllllll"), (a = b ? c : "lllllllllllllllllllllll");
// After
(a = b ? c : 'lllllllllllllllllllllll'),
(a = b ? c : 'lllllllllllllllllllllll'),
(a = b ? c : 'lllllllllllllllllllllll'),
(a = b ? c : 'lllllllllllllllllllllll'),
(a = b ? c : 'lllllllllllllllllllllll')
We took the stance with prettier to remove all the trailing whitespaces. We used to not touch comments because it's user generated, but that doesn't mean that they should have whitespace :)
// Before
// There is some space here ->______________
// After
// There is some space here ->
Our handling for comments inside of the class declaration was very naive, we would just move all the comments to the top. We now are more precise and respect the comments that are interleaved inside of decorators and around extends
.
// Before
// A
// B
// C
@Foo()
@Bar()
class Bar {}
// After
// A
@Foo()
// B
@Bar()
// C
class Bar {}
Bind expressions are being discussed at TC39 and we figured we could print it with prettier. We used to be very naive about it and just chain it. Now, we use the same logic as we have for method chaining with the .
operator for it. We also fixed some edge cases where it would output invalid code.
// Before
observable::filter(data => data.someTest)::throttle(() =>
interval(10)::take(1)::takeUntil(observable::filter(data => someOtherTest))
)::map(someFunction);
// After
observable
::filter(data => data.someTest)
::throttle(() =>
interval(10)::take(1)::takeUntil(observable::filter(data => someOtherTest))
)
::map(someFunction);
It's being discussed at TC39 to be able to make the argument of a catch(e)
optional. Let's make sure we can support it in prettier if people use it.
// Before
Syntax error
// After
try {} catch {}
Another new proposal being discussed at TC39 is an optional chaining syntax. This is currently a stage 1 proposal, so the syntax may change at any time.
obj?.prop // optional static property access
obj?.[expr] // optional dynamic property access
func?.(...args) // optional function or method call
Comments are tricky to get right, but especially when they have meaning based on where they are positioned. We're now special casing the way we deal with comments used as type cast for Closure Compiler such that they keep having the same semantics.
// Before
let assignment /** @type {string} */ = getValue();
// After
let assignment = /** @type {string} */ (getValue());
It looks kind of odd to have a computed property lookup on the next line, so we added a special case to inline it.
// Before
data
[key]('foo')
.then(() => console.log('bar'))
.catch(() => console.log('baz'));
// After
data[key]('foo')
.then(() => console.log('bar'))
.catch(() => console.log('baz'));
The flow team introduced two very exciting features under a new syntax. We now support them in prettier. I've personally been waiting for opaque types for a veerrryyyy long time!
// Before
Syntax error
// After
opaque type ID = string;
export type * from "module";
We've been doing this on JavaScript objects since the early days of prettier but forgot to apply the same thing to Flow and TypeScript types.
// Before
type A = {
"string": "A";
}
// After
type A = {
string: "A";
}
Oopsy, we were dropping the generic in this very specific case.
// Before
type myFunction = A => B;
// After
type myFunction = <T>(A) => B;
Parenthesis... someday we'll get all of them fixed :)
// Before
const actionArray: () => void[] = [];
// After
const actionArray: (() => void)[] = [];
TypeScript 2.5 RC was recently announced, allowing you to use the upcoming "optional catch binding" syntax in TypeScript, too.
// Before
namespace global {
export namespace JSX { }
}
// After
global {
export namespace JSX {}
}
Thanks to the untyped and permissive nature of JavaScript, we've been able to concat undefined to a string and get some interesting code as a result. Now fixed for this case :)
// Before
<undefined.Author />
// After
<this.Author />
We want to make sure that all the special cases that we added for JavaScript and Flow also work for TypeScript constructs. In this case, objects should also hug if they are wrapped in a as
operator.
// Before
const state = JSON.stringify(
{
next: window.location.href,
nonce,
} as State
);
// After
const state = JSON.stringify({
next: window.location.href,
nonce,
} as State);
Most of the time we add parenthesis for correctness but in this case, we added them for nothing, so we can just get rid of them and have a cleaner code :)
// Before
(<x>a) || {};
// After
<x>a || {};
Yet another case of missing parenthesis. Thankfully we're getting very few of them nowadays and they are for extremely rare edge cases.
// Before
foo.bar as Baz = [bar];
// After
(foo.bar as Baz) = [bar];
The declare
keyword doesn't do anything for interface
so we never put it there. However, it felt weird if you were in a declaration file and seeing everything have declare
before it except for interfaces. So now we reprint declare
if it was there in the first place.
// Before
interface Dictionary<T> {
[index: string]: T
}
// After
declare interface Dictionary<T> {
[index: string]: T
}
In order to get a first version of CSS to ship, we kept string quotes as is. We are now respecting the singleQuote
option of prettier. The difficulty here was to make sure that we output correct code for all the crazy escapes, unicode characters, emoji, special rules like charset which only work with double quotes...
// Before
div {
content: "abc";
}
// After
div {
content: 'abc';
}
Another place where we can reuse the logic we've done for JavaScript to improve CSS printing.
// Before
border: 1px solid rgba(0., 0.0, .0, .3);
// After
border: 1px solid rgba(0, 0, 0, 0.3);
I can never quite remember the rules behind quotes around attributes so we're now always putting quotes there.
// Before
a[id=test] {}
// After
a[id="test"] {}
// Before
const header = css`.top-bar {background: black;margin: 0;position: fixed;}`
// After
const header = css`
.top-bar {
background: black;
margin: 0;
position: fixed;
}
`;
styled-components has a lot of different variants for tagging template literals as CSS. It's not ideal that we've got to encode all those ways inside of prettier but since we started, might as well do it for real.
styled(ExistingComponent)`
css: property;
`;
styled.button.attr({})`
border: rebeccapurple;
`;
The CSS parsers we use do not give us a 100% semantic tree: in many occasions they bail and just give us what is being entered. It's up to us to make sure we clean this up while maintaining correctness. In this case, we just printed spaces between selectors as is but we know it's correct to always replace it by a single space.
// Before
.hello
.how-you-doin {
height: 42;
}
// After
.hello .how-you-doin {
height: 42;
}
I still have nightmares from dealing with BOM in a previous life. Thankfully, in 2017 it's no longer a big issue as most tooling is now aware of it. Thanks @azz for fixing an edge cases related to CSS parsing.
// Before
[BOM]/* Block comment *
html {
content: "#{1}";
}
// After
[BOM]/* Block comment */
html {
content: "#{1}";
}
If you tried to use the range formatting feature in a GraphQL file, it would throw an exception, now it properly worked again and only reformats the piece you selected.
.gql
file extension to be parsed as GraphQL (#2357) by @rrdelaneyAt Facebook, we use .graphql
extension but it looks like it's common to have .gql
as well, doesn't cost a lot to support it in the heuristic that figures out what parser to use.
It was already possible to have multiple glob patterns but they would be additive, with this change, you can add a glob pattern to ignore some files. It should be very handy to ignore folders that are deeply nested.
prettier --write '{**/*,*}.{js,jsx,json}' '!vendor/**'
This is a handy way of knowing if prettier would print a piece of code in a different way. We already had all the concepts in place, we just needed to wire them up correctly.
$ echo 'call ( ) ;' | prettier --list-different
(stdin)
$ echo $?
1
Update to this version instead 🚀
This release features some bugfixes and tweaks around JSX, TypeScript, CSS, and JavaScript formatting, as well as a couple new features.
We received a lot of community feedback about the changes we made to JSX formatting in the 1.6.0 release, and have made changes to bring formatting closer to community standards and expectations.
In 1.6.0, we added a second style for ternaries (conditional expressions, a ? b : c
), based on a format popular in the community where parentheses are used to demarcate JSX content:
const DinnerOptions = ({ willEatMeat, willEatEggs, willEatVegetables }) => (
<div>
<div>Let's get some dinner...</div>
{willEatMeat ? (
<FullMenu />
) : willEatEggs ? (
<VegetarianMenu />
) : willEatVegetables ? (
<VeganMenu />
) : (
<BackupMenu />
)}
</div>
);
Before this was added, prettier only formatted ternaries with one consistent style:
willEatMeat
? "Full Menu"
: willEatEggs
? "Vegetarian Menu"
: willEatVegetables ? "Vegan Menu" : "Backup Menu";
In 1.6.0, we used the following heuristic to decide when to use the new "JSX mode ternaries":
We should print a ternary using JSX mode if:
* The ternary contains some JSX in it
OR
* The ternary appears inside of some JSX
However, this heuristic caused some unexpected formatting:
So, in 1.7.0, we have revised our heuristic to just be:
We should print a ternary using JSX mode if:
* The ternary contains some JSX in it
We hope that this change will result in fewer surprising ternaries.
A big thanks goes out to @duailibe who implemented this change in addition to several other JSX-related formatting issues that were reported.
We spent some time this release polishing our CSS formatting, and as part of that, @lydell did some work to normalize letter case.
So now, almost everything in CSS will print using lower case
.
/* Before */
DIV.Foo {
HEIGHT: 12PX;
}
/* After */
div.Foo {
height: 12px;
}
Don't worry, though – Prettier won't touch your $scss-variables
, @less-variables
, or FunctionNames()
. Preprocess on!
There is a new option called --require-pragma
(requirePragma
via the API) which will change prettier's behavior so that it only reformats a file if it has a special "pragma" comment at the top of it, that looks like this:
/**
* @prettier
*/
or
/**
* @format
*/
This was @ajhyndman's idea and it was implemented by @wbinnssmith.
There was a bug in Prettier 1.6.1 where an error would be thrown while parsing any TypeScript using the never
type, for example:
Observable.empty<never>();
Also, Prettier 1.6.1 was incorrectly removing the declare
keyword from enum
declarations in *.d.ts
files:
// In
declare const enum Foo {}
// Out
const enum Foo {}
Both of these issues have been fixed. Thanks to @JamesHenry and @existentialism for these fixes which support our TypeScript community!
There is a new CLI option --config-precedence
which configures how prettier should prioritize config sources. Valid values are:
cli-override
(default) - CLI options take precedence over config file
file-override
- Config file take precedence over CLI options
prefer-file
- If a config file is found will evaluate it and ignore other CLI options. If no config file is found CLI options will evaluate as normal.
This option adds support to editor integrations where users define their default configuration but want to respect project specific configuration.
prettier.resolveConfig.sync
Previously, there was no way via the API to resolve configuration for a source file synchronously. Thanks to some new additions to cosmiconfig
by @sudo-suhas, @ikatyang was able to add support for this to the prettier API.
.sync()
method by @ikatyangresolveConfigFile.sync()
by @ikatyangcross-spawn
by @ikatyangfiles:
over types:
in pre-commit configuration by @asottilequery
) by @azz?:
instead of ?!
by @ikatyangdeclare
modifier from enum
reported by @mariusschulzThank you to everyone who contributed to this release, be it through issue creation, code contribution, code review, or general commenting and feedback. Prettier is a community-run project and is able to continue to exist thanks to people like you. Thank you!
Update to this version instead 🚀
This release adds Markdown support, a new --insert-pragma
flag, fixes a number of formatting issues, adds support for some new experimental operators, and improves our editor integration support.
You can now run Prettier on Markdown files!
The implementation is highly compliant with the CommonMark spec, and backed by the excellent remark-parse
package.
Word Wrap
One of Prettier's core features is its ability to wrap code at a specified line length. This applies to Markdown too, which means you can maintain nice and clean 80-character-wide Markdown files without having to re-adjust line breaks manually when you add or delete words.
Input:
Voilà! In view, a humble vaudevillian veteran cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valourous visitation of a bygone vexation stands vivified and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition! The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honour to meet you and you may call me V.
Output:
Voilà! In view, a humble vaudevillian veteran cast vicariously as both victim
and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity,
is a vestige of the vox populi, now vacant, vanished. However, this valourous
visitation of a bygone vexation stands vivified and has vowed to vanquish these
venal and virulent vermin vanguarding vice and vouchsafing the violently vicious
and voracious violation of volition! The only verdict is vengeance; a vendetta
held as a votive, not in vain, for the value and veracity of such shall one day
vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage
veers most verbose, so let me simply add that it's my very good honour to meet
you and you may call me V.
Note for CJK users: If your markdown renderer does not support CJK line ending, you'll have to use plugin like markdown-it-perfect-newline-for-cjk, hexo-filter-fix-cjk-spacing, etc. to remove additional spaces.
// Source 一二三 四五六 七八九 // Rendered content with unsupported renderer 一二三 四五六 七八九 // Rendered content with supported renderer or via plugin 一二三四五六七八九
Code Formatting
Powered by Prettier's generic "multiparser", Prettier will format code blocks in Markdown! We use the language code provided with the code block to determine which language it is, and thus we can format any language that Prettier supports (including Markdown itself, if you're into that).
Input:
```js
reallyUgly (
javascript
)
```
```css
.h1 { color : red }
```
Output:
```js
reallyUgly(javascript);
```
```css
.h1 {
color: red;
}
```
Note: In some cases you may not want to format your code in Markdown, and just like in other languages, in Markdown you can use
<!-- prettier-ignore -->
before the code block to ignore it from formatting.
Lists
When rearranging list items, after running Prettier all the numbers will be fixed!
Note: you can actually opt out of this by using
1.
for all list items if you want to optimize for cleaner diffs.
Tables
Tables will also automatically be adjusted to fit their contents. This could be completely unmaintainable without an automated tool.
Markdown-in-JS
By using either md
or markdown
tagged template literals, you can format markdown code inside JavaScript.
const markdown = md`
# heading
1. list item
`;
@format
to first docblock if absent (#2865) by @samouriIn 1.7, we added an option called --require-pragma
to require files contain an /** @format */
pragma to be formatted. In order to add this pragma to a large set of files you can now use --insert-pragma
flag.
prettier --write "folder/**/*.js" --insert-pragma
--loglevel
option (#2992) by @ikatyangThis nifty feature allows you to opt in (or out) of Prettier's logging. We've also cleaned up the logging substantially since 1.7.
$ prettier --loglevel=debug blarg
$ ./bin/prettier.js --loglevel=debug blarg
[debug] normalized argv: {"_":["blarg"],"bracket-spacing":false,"color":true,"debug-check":false,"debug-print-doc":false,"flow-parser":false,"insert-pragma":false,"jsx-bracket-same-line":false,"list-different":false,"require-pragma":false,"semi":false,"single-quote":false,"stdin":false,"use-tabs":false,"version":false,"with-node-modules":false,"write":false,"loglevel":"debug","ignore-path":".prettierignore","config-precedence":"cli-override"}
[error] No matching files. Patterns tried: blarg !**/node_modules/** !./node_modules/**
This has been a long-time known issue with Prettier. When formatting code that results in a change of indentation level, the JSDoc comments would end up being out of alignment. We're happy to report this is now fixed!
// Before
function theFunction2(action$, store) {
/*
* comments
*/
return true;
}
// After
function theFunction2(action$, store) {
/*
* comments
*/
return true;
}
We've added support for two new proposed operators to Prettier: the pipeline operator and the nullish coalescing operator.
The pipeline operator is currently a stage one proposal.
This proposal introduces a new operator |> similar to F#, OCaml, Elixir, Elm, Julia, Hack, and LiveScript, as well as UNIX pipes. It's a backwards-compatible way of streamlining chained function calls in a readable, functional manner, and provides a practical alternative to extending built-in prototypes.
// Before
let result = exclaim(capitalize(doubleSay("hello")));
// After
let result = "hello"
|> doubleSay
|> capitalize
|> exclaim;
The nullish coalescing operator is another stage one proposal.
When performing optional property access in a nested structure in conjunction with the optional chaining operator, it is often desired to provide a default value if the result of that property access is null or undefined.
This operator is similar to ||
except it only evaluates the right-hand-side if the left is undefined
or null
, not ""
, 0
, NaN
, etc.
const foo = object.foo ?? "default";
This was another known issue with Prettier, when printing a template literal string with expressions inside that went over the print width, it would wrap the code in weird places inside the expressions. Now, if Prettier needs to insert a line break, it should happen right between ${
and }
.
// Before
const description = `The value of the ${cssName} css of the ${this
._name} element`;
const foo = `mdl-textfield mdl-js-textfield ${className} ${content.length > 0
? "is-dirty"
: ""} combo-box__input`;
// After
const description = `The value of the \${cssName} css of the \${
this._name
} element`;
const foo = `mdl-textfield mdl-js-textfield ${className} ${
content.length > 0 ? 'is-dirty' : ''
} combo-box__input`
}
for arrow functions attributes (#3110) by @duailibeIn order to align closer to the Airbnb style guide, and since it was never intentionally printed this way, we've moved the }
from to the next line in JSX. This is more diff friendly, and makes it easier to move code around by shifting lines in your editor.
// Before
<BookingIntroPanel
logClick={data =>
doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data)}
/>;
// After
<BookingIntroPanel
logClick={data =>
doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data)
}
/>;
There was a bug in the heuristic that Prettier uses to determine whether an expression is a factory or not. It now works correctly with longer member expressions.
// Before
window.FooClient
.setVars({
locale: getFooLocale({ page }),
authorizationToken: data.token
})
.initVerify("foo_container");
// After
window.FooClient.setVars({
locale: getFooLocale({ page }),
authorizationToken: data.token
}).initVerify("foo_container");
Printing comments in the right place is an endless challenge
// Before
function f(/* comment*/ promise) {}
// After
function f /* comment*/(promise) {}
Member chains are one of the most complex parts of Prettier. This PR fixes an issue where repeated calls lead to the next method not being pushed to the next line.
// Before
wrapper
.find("SomewhatLongNodeName")
.prop("longPropFunctionName")().then(function() {
doSomething();
});
// After
wrapper
.find("SomewhatLongNodeName")
.prop("longPropFunctionName")()
.then(function() {
doSomething();
});
Previously, Prettier would delete all newlines within a member chain. Now we keep up to one if it's in the source. This is nice for fluent APIs that you want to break up over multiple lines.
angular
.module("AngularAppModule")
// Constants.
.constant("API_URL", "http://localhost:8080/api")
// App configuration.
.config(appConfig)
.run(appRun);
This addresses an issue where due to our special object inline behaviour, the indentation missing from the function call.
// Before
db.collection("indexOptionDefault").createIndex({ a: 1 },
{
indexOptionDefaults: true
},
function(err) {
// code
});
// After
db.collection("indexOptionDefault").createIndex(
{ a: 1 },
{
indexOptionDefaults: true
},
function(err) {
// code
}
);
Similarly, there was another edge case where indentation was missing from logical expressions. This is fixed, too.
// Before
const someLongVariable = (idx(
this.props,
props => props.someLongPropertyName
) || []
).map(edge => edge.node);
// After
const someLongVariable = (
idx(this.props, props => props.someLongPropertyName) || []
).map(edge => edge.node);
There are so many ways to break a line. Some of them look much worse than others. Breaking between in this case looked really weird, so it has been fixed!
// Before
function functionName() {
if (true) {
this._aVeryLongVariableNameToForceLineBreak = new this
.Promise((resolve, reject) => {
// do something
});
}
}
// After
function functionName() {
if (true) {
this._aVeryLongVariableNameToForceLineBreak = new this.Promise(
(resolve, reject) => {
// do something
}
);
}
}
In a method chain we split lines by grouping elements together and accessing an array should be printed in the end of a group instead of the beginning.
// Before
find('.org-lclp-edit-copy-url-banner__link')
[0].getAttribute('href')
.indexOf(this.landingPageLink)
// After
find('.org-lclp-edit-copy-url-banner__link')[0]
.getAttribute('href')
.indexOf(this.landingPageLink)
This was a minor alignment bug in intersection types, and has now been fixed.
// Before
type intersectionTest = {
propA: X
} & {
propB: X
} & {
propC: X
} & {
propD: X
};
// After
type Props = {
propA: X
} & {
propB: X
} & {
propC: X
} & {
propD: X
};
We missed a case where we need to keep the parenthesis with TypeScript's as
assertions. This is now fixed.
// Before
aValue as boolean ? 0 : -1;
// After
(aValue as boolean) ? 0 : -1;
This fixes up the issue where JSX formatting occasionally needed to be run twice to become stable. This occurred when you had multiple JSX whitespace elements or JSX whitespace followed by a space.
// Before
<div>
{" "} <Badge src={notificationIconPng} />
</div>;
// After
<div>
{" "}
<Badge src={notificationIconPng} />
</div>
This was an issue with the --jsx-bracket-same-line
option. Turns out you can't always put the bracket on the same line...
// Input
<div
// comment
>
{foo}
</div>
// Before
<div>
// comment
{foo}
</div>;
// After
<div
// comment
>
{foo}
</div>;
Prettier will now preserve line breaks included in the source code when formatting the grid
and grid-template-*
rules, since those are important to keep in separate lines, but still applies the formatting like other rules (e.g., numbers and quotes).
/* Original Input */
div {
grid:
[wide-start] 'header header header' 200.000px
[wide-end] "footer footer footer" .50fr
/ auto 50.000px auto;
}
/* Before */
div {
grid: [wide-start] "header header header" 200px [wide-end]
"footer footer footer" 0.5fr / auto 50px auto;
}
/* After */
div {
grid:
[wide-start] "header header header" 200px
[wide-end] "footer footer footer" 0.5fr
/ auto 50px auto;
}
Turns out SCSS maps are much prettier when printed over multiple lines.
// Before
$map: (color: #111111, text-shadow: 1px 1px 0 salmon)
// After
$map: (
color: #111111,
text-shadow: 1px 1px 0 salmon
);
Prettier will now format the CSS in styled-components code that looks like this:
styled(Component).attrs({})`
color: red;
`;
Prettier doesn't support formatting JavaScript expressions in GraphQL. See #2640 for tracking. There was a bug where formatting an expression lead to invalid code, so we've completely disabled formatting GraphQL when it contains JavaScript expressions until we fully support it.
// Before
(invalid code)
// After
graphql(schema, `{ query test { id }} ${fragment}`)
Previously, piping the output of --list-different
to other tools was troublesome due to the ANSI color codes we use to show whether a file was modified or not. This PR disables the use of color when Prettier is piped to a different process.
This fixes a bug where passing a path starting with ./
to the CLI wouldn't match patterns used in .prettierignore
.
# .prettierignore
path/to/*.js
After this fix, no files will be written to when executing:
$ prettier --write ./path/to/*.js
This fixes an issue where .prettierrc
overrides, under certain conditions, were not being respected for absolute paths with the resolveConfig
API.
Chinese, Japanese and Korean characters are now considered two characters wide.
// Before (exceeds print width when CJK characters are 2x monospace chars)
const x = ["中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文"];
// After
const x = [
"中文",
// ...
"中文"
];
#3015 also ensures that combining characters (e.g. Á
) are counted as one character.
We've added a new function to the API (prettier.getSupportInfo([version])
), and the CLI --support-info
. This can be used to interrogate Prettier to find out which languages the current version, or an older version, supports. It also provides useful information such as CodeMirror IDs, tmScopes, etc, which can be used to automate some of the work done with lookup tables in text editor integrations.
Internally, we use this information to drive which extensions trigger which parsers, and support some common files that don't have extensions, like .prettierrc
, Jakefile
, etc.
# prettier knows that this file is JSON now.
$ prettier --write .prettierrc
This fixes an issue in editors that support range formatting, where formatting an object would cause Prettier to crash.
Thanks to everyone who contributed to this release, as well as those who raised issues! Prettier has become a highly stable piece of software that a large amount of people trust with their code. We take that trust seriously, and fix rare issues that break code with the highest priority. We can't fix these issues if we don't know about them, so never be afraid to create an issue!
Update to this version instead 🚀
This release adds an option for arrow function parens in arguments, support for the new JSX fragment syntax (<>
), support for .editorconfig
files, and nice additions to our GraphQL and Markdown support.
When printing arrow functions, Prettier omitted parens around the arguments if they weren’t strictly necessary, like so:
// no parens
foo => {};
// parens
(foo: Number) => {};
// parens
({ foo }) => {}
// parens
(foo = 5) => {}
This lead to the most commented thread in our issue tracker. Prettier now has the --arrow-parens
option (arrowParens
in the config) that can assume two values today:
"avoid"
- (default) preserve the behavior that omits parens when possible"always"
- always includes parensPrettier will now recognize and format JSX with the new fragment syntax, like the code below:
function MyComponent() {
return (
<>
<Children1 />
<Children2 />
<Children3 />
</>
);
}
We received feedback that formatting a JSX file with a really long text (~1000 lines) was really slow and noticed there was two performance bottlenecks in our fill
primitive, which prints text until it reaches the print width and then insert a line break.
After the release of our Markdown support, we received feedback that breaking text to respect the print width could affect some renderers that could be sensitive to line breaks. In 1.8.2 we released a new option proseWrap: false
that would print a paragraph in a single line, and users would rely on the "soft wrapping" feature of editors.
In 1.9 we are releasing a new option proseWrap: "preserve"
which will respect the original line breaks of text, and lets the users decide where the text should break.
[WARNING] proseWrap
with boolean value is deprecated, use "always"
, "never"
or "preserve"
instead.
[BREAKING CHANGE] proseWrap
option now defaults to "preserve"
as some renderers are linebreak-sensitive.
When GraphQL support was released, Prettier did not support interpolation so it would skip formatting if any interpolations were present, because interpolations make formatting very difficult. While that works well for the most part, users of the Apollo Client were missing out on Prettier’s GraphQL support sometimes, because Apollo Client uses interpolation to share fragments between queries. The good news is that only top-level interpolations are allowed, and that was way easier to add support for in Prettier.
In 1.9 we format GraphQL queries with top-level interpolation:
gql`
query User {
user(id: "Bob") {
...UserDetails
}
}
${UserDetailsFragment}
`
(Prettier will continue to skip formatting if the interpolation is inside a query or mutation or so.)
Prettier will now respect intentional line breaks inside GraphQL queries (but limit to 1), where before it would remove them.
query User {
name
age
}
CSS is mostly case insensitive, so Prettier has been lowercasing stuff for a while to keep things consistent. Turns out we overlooked a detail in the CSS spec. Element and attribute names in selectors depend on the markup language: In HTML they are case insensitive, but in SVG (XML) they are not. Previously Prettier would incorrectly lowercase element and attribute names, but now we don’t anymore.
It's taken a while, but Prettier will finally respect your .editorconfig
file. This includes:
indent_style
indent_size
/tab_width
max_line_length
The prettier
CLI respects .editorconfig
by default, but you can opt out with --no-editorconfig
.
However, the API doesn't respect .editorconfig
by default, in order to avoid potential editor integration issues (see here for details). To opt in, add editorconfig: true
to the prettier.resolveConfig
options.
Prettier won't break an element with no attributes anymore, keeping elements like <br />
as an unit.
In the previous release we tried a new strategy of breaking template literals with expressions inside to respect the print width. We've received feedback that for some cases it was actually preferred that it would exceed print width than breaking in multiple lines.
From now on, template literals expressions that contain a single identifier won't break anymore:
const foo = `Hello ${username}. Today is ${month} ${day}. You have ${newMessages} new messages`.
Fixes an edge case where Prettier was moving comments around breaking tools like Webpack:
const API = {
loader: () => import('./test' /* webpackChunkName: "test" */),
};
// would get formatted to
const API = {
loader: (/* webpackChunkName: "test" */) => import("./test")
};
There was a case where comments between a decorator and a class property were moved to an invalid position.
// Before
class Something {
@decorator
static // comment
property = 1;
}
// After
class Something {
@decorator
// comment
static property = 1;
}
It won't break empty type parameters (foo: Type<>
) anymore.
We were accidentally dropping flow mixins, this has been fixed, but only for the babylon
parser.
// Before
class Foo extends Bar {}
// After
class Foo extends Bar mixins Baz {}
This was inconsistent with JavaScript and Flow, Prettier won't print a trailing comma in the following cases, when using the TypeScript parser:
const {
bar,
baz,
...rest
} = foo;
We were omitting parens around type assertions inside decorators:
@(bind as ClassDecorator)
class Decorated {}
inlineCode
(#3230) by @ikatyangPrettier won't break text inside inlineCode
meaning it will only break of after it.
Fixes cases where Prettier would insert extra whitespace like in the following examples:
扩展运算符(spread )是三个点(`...`)。
This is an english paragraph with a CJK quote " 中文 ".
Fixes the case where \_\_text\_\_
would be formatted as __text__
.
Prettier now considers not only ASCII punctuation characters but Unicode as well.
We already supported YAML in the front matter of Markdown files and we added the TOML format as well, since some static site generators support it.
+++
date: '2017-10-10T22:49:47.369Z'
title: 'My Post Title'
categories: ['foo', 'bar']
+++
This is the markdown body of my post.
Fixes a bug where it would indent lines after a list when it shouldn't:
* parent list item
* child list item
* [x] parent task list item
* [x] child task list item
would become:
* parent list item
* child list item
* [x] parent task list item
* [x] child task list item
Non-breaking whitespaces are useful to keep words separated by spaces together in the same line (i.e. number and units or multi-word product names). Prettier was wrongfully converting them to regular whitespaces.
Fixes a bug where Prettier could break text if it went over the print width right before a number followed by .
which would be parsed as a numbered list:
She grew up in an isolated village in the 19th century and met her father aged
29. Oh no, why are we in a numbered list now?
Prettier will omit the semicolon (before and after) inside code samples if it's a simple JSX expression:
No semi:
```jsx
<div>Example</div>
```
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Version 1.5.0 of prettier just got published.
The version 1.5.0 is not covered by your current version range.
Without accepting this pull request your project will work just like it did before. There might be a bunch of new features, fixes and perf improvements that the maintainers worked on for you though.
I recommend you look into these changes and try to get onto the latest version of prettier. Given that you have a decent test suite, a passing build is a strong indicator that you can take advantage of these changes by merging the proposed change into your project. Otherwise this branch is a great starting point for you to work on the update.
Release Notes
1.5.0: GraphQL, CSS-in-JS & JSONThis is the release I've been waiting for a very long time: one that has only minimal changes to JavaScript!
For the past 6 months, we kept doing changes to various aspects of printing JavaScript, with the hope that one day we would get to a stable place. No automated tool is going to print perfect code for all the possible edge cases. The goal is to find a good place where when people report code that is printed in a funny way, we can't make it better without making other pieces of code look worse, introduce behavior that's very hard to understand for humans and doesn't introduce some disproportionate complexity to the codebase.
We're not 100% there yet, but we're closer than ever!
Now that JavaScript needs for support is trending down, it's an opportunity to support other languages that front-end developers are working on and want formatted. We've introduced TypeScript and CSS in the last release and are doing a batch of fixes for them in this release. We're also adding support for new languages: GraphQL queries, embedding CSS-in-JS and JSON are now available in prettier!
Blog Post: Adding a new layout strategy to Prettier by @karl
Prettier is not only a useful tool but it's also a really cool piece of technology. @karl spent a bunch of time improving JSX support and in the process implemented a new primitive to prettier:
fill
. He wrote a very interesting blog post Adding a new layout strategy to Prettier that I highly recommend reading if you're interested in how prettier is working behind the scenes.GraphQL
Thanks to @stubailo, @jnwng, @tgriesser and @azz, prettier now supports printing GraphQL queries!
It works for
.graphql
files and within JavaScipt templates that start withgraphql
,graphql.experimental
andgql
in order to work with Relay and Apollo.Note that it only supports the open source syntax of GraphQL, therefore doesn't work with Relay Classic, it only works with Relay Modern.
CSS-in-JS
If you are using styled-components or styled-jsx, prettier will now reformat the CSS inside of your template expressions.
JSON
This was pretty straightforward to implement but nonetheless very useful. Thanks to @josephfrazier for doing it :)
CSS
I'm really excited because we only put a few days to build the initial CSS support and it has worked surprisingly well. This release brings a handful of important improvements to CSS but nothing that required big changes.
CSS: Every selector is now printed in its own line (#2047) by @yuchi
The biggest unknown when printing CSS was how to deal with multiple selectors. The initial approach we took was to use the 80 columns rule where we would only split if it was bigger than that. Many people reported that they were using another strategy for this: always break after a
,
. It turns out that many popular codebases are using this approach and it feels good as you can see the structure of the selectors when layed out on-top of each others.CSS: lowercase hex colors (#2203) by @azz
The concept of code formatting has blurry boundaries. The core aspect of it is around whitespaces but some things like single vs double quotes and semi-colons are usually bundled with it. With prettier on JavaScript, we also lightly reformat strings by removing extra
\
and normalize numbers. For CSS, we need to do a similar interpretation of where the boundary ends. For colors, we decided to turn all the letters into lowercase and stop there. Turning rgb() into hex or 6 hex into 3 hex is out of scope.CSS: Use fill for CSS values (#2224)
The new fill primitive turned out to be very useful for CSS. For long values, instead of breaking and putting a
\n
before every element, we can instead only put a\n
when it goes over the limit. It leads to much better looking code.CSS: Allow long media rules to break (#2219)
This is another small fix in the journey of properly supporting a new language. We now encode the ability to break on long
@media
rules.CSS: Print @else on same line as } (#2088) by @azz
Less and Scss are turning into real programming languages :) Step by step, we're starting to print all their constructs in the same way as JavaScript. This time, it's the
else
placement.CSS: implement prettier-ignore (#2089) by @azz
While we want prettier to format the entire codebase, there are times where we "know better" and want an escape hatch. This is where the
prettier-ignore
comment comes in. It wasn't working for CSS but that was an oversight, now it is implemented :)CSS: Fix css-modules composes breaking with long line width (#2190) by @tdeekens
In order to be fast, many "packagers" do not parse files in order to extract dependencies but instead use a crude regex. This is a reason why we don't break long
require()
calls and it happens to also affect CSS Modules. If you add new lines in thecomposes
field, it doesn't recognize it anymore. So we're no longer breaking it there, even if it goes over 80 columns.CSS: First try scss when there's an @import with comma (#2225)
We made a decision to have only a single high level "parser" for CSS, SCSS and Less even though we are using
postcss-less
andpostcss-scss
under the hood. We use a regex to figure out which parser to try first and fallback to the other one if a syntax error is thrown. Unfortunately, for certain features, the first (incorrect) parser doesn't throw and instead skips some elements. So, we need to beef up the regex to make sure we are right for the early detection.Thankfully, this hack is working well in practice. If we find a lot more edge cases, we'll likely want to do the right thing(tm) and split them into two parsers.
TypeScript
TypeScript support is now solid, all the changes for this release are small edge cases.
TypeScript: print arrow function type params on same line as params (#2101) by @azz
The core algorithm of prettier is to expand a group if all the elements do not fit. It works really well in practice for most of JavaScript but there's one case it doesn't handle very well is when there are two groups side by side, in this case:
<Generics>(Arguments)
. We have to carefully create groups such that arguments expand first as this is generally what people expect.TypeScript: keep parens around with yield/await non-null assertion (#2149) by @azz
For better or worse, we decided to manually handle adding parenthesis. So when a new operator is introduced, we need to make sure that we add correct parenthesis when nested with any other combination of operators. In this case, we missed await inside of TypeScript
!
.TypeScript: Print {} in import if it's in the source (#2150) by @azz
We use typescript-eslint-parser project that translates TypeScript AST into estree AST in order for prettier to print it. From time to time we're going to find edge cases that it doesn't handle yet. In this case, it didn't give a way to tell that there's an empty
{}
, which apparently is important for TypeScript. Thankfully, the team is very responsive and they fixed it after we put a workaround inside of prettier.TypeScript: Always break interfaces onto multiple lines (#2161) by @azz
The code that implements
interface
is shared with the code that printsobject
s, which contains a rule to keep them expanded if there's a\n
inside. But, this is not the intended behavior for interfaces. We always want to expand, like we do for classes, even if it fits 80 columns.TypeScript: Fix extra semicolon in ambient typescript declaration emit (#2167) by @azz
no-semi
andsemi
are often requested but on the prettier team we're one step ahead and implementedtwo-semi
for you! Just kidding, it was a bug and is now fixed ;)TypeScript: group function params in call/construct signatures (#2169) by @azz
Adding a comment before a method used to take into account the comment length and would often expand the method when it wasn't expected. Thankfully, it was a simple fix, just wrap the output in a
group
.TypeScript: Upgrade tsep (#2183) by @azz
This bug was very annoying if you ran into it: anytime you formatted the code, it would add one more
_
to the object key!TypeScript: break on multiple interface extends (#2085) by @azz
Unlike in JavaScript, TypeScript lets you extend multiple classes at once. It turns out that people use this feature and prettier now does a better job at printing it.
TypeScript: handle ObjectPattern instead of ObjectExpression inside BinaryExpression (#2238) by @azz
This one isn't very interesting, it's an edge case that's not properly handled in the TypeScript -> estree conversion.
Preserve lines after directives (#2070)
By supporting TypeScript, prettier is now being used in a lot of Angular codebases which exercises edge cases that were not properly handled. In this case, we didn't preserve empty lines after directives inside of a function.
JavaScript
This release is very light in terms of JavaScript changes, which is awesome. We're starting to see the light at the end of the tunnel and get towards a great pretty printer. We're never going to get to a 100% perfect automatic pretty printer. The goal is that for every issue we get, there are no clear ways to improve the way it is printed without regressing other pieces.
Allow JSX lines to be recombined (#1831) by @karl
The goal of prettier is to have a consistent way to format your code: given an AST, we always print the same way. In two places we had to compromise and read the original format: JSX and Objects. With this change, we're no longer relying on the original input for JSX with text inside. This lets us reflow
Break on non-literal computed member expression (#2087) by @azz
Printing member chains is the most complicated piece of prettier and we keep finding small tweaks we can do to make it a better experience.
Indent first variable in one-var scenario (#2095) by @azz
Up until recently we haven't done much to support printing multiple variables in a single declaration as the most common practice is to do one variable declaration per variable. For single declarations, we don't want to indent it, but it turns out that we do when there are other ones afterwards, otherwise it looks weird.
Allow break with both default named import (#2096) by @azz
This one is an unfortunate regression from 1.4 where we inlined import that only contained a single element. Turns out the definition of a single element allowed a single type and a single element. This is now corrected!
Turn allowImportExportEverywhere on (#2207) by @zimme
The goal of prettier is to format code people write in practice, so we enable loose/experimental modes for all the parsers we support. Babylon allows you to write import within a function, which is not part of the standard, but it doesn't cost us much to allow it.
Support inline template for new calls (#2222)
We keep adding features for function calls and have to backport them to new calls as they have a different AST node type but in practice we want to treat them the same. This fix refactored the two so that they are going through the same call site, so hopefully should prevent more from sneaking in.
Don't indent + in object value (#2227)
When we switched to using the same heuristic for assignment (
a = b
) for objects ({a: b}
), we forgot to fix the indentation. Now it's fixed.Handle conditions inside of a ternary (#2228)
Prettier already had a special case when the expression was a conditional but it didn't apply when the conditional was the left part of a ternary. Now it does.
Add caching for printing (#2259)
With the 1.0 release, we fixed a bug in the printing that introduced an exponential behavior. We've been able to mitigate the biggest issue such that reasonable code didn't time out, but it wasn't completely fixed it. By adding a caching layer at the right spot, we should now be in the clear.
This should make printing the IR of prettier using prettier in debug mode no longer time out.
Fix variance location (#2261)
We refactored the code that prints modifiers when we introduced TypeScript support and accidentally moved around the variance (
+
) part beforestatic
which is not valid in Flow. This is now fixed.Miscellaneous
Various fixes for range and cursor tracking (#2266, #2248, #2250, #2136) by @CiGit and @josephfrazier
Both those features were introduced in the last release and we discovered a bunch of issues when actually using them in production. A bunch of them got fixed, if you see more, please report them!
Not sure how things should work exactly?
There is a collection of [frequently asked questions](https://greenkeeper.io/faq.html) and of course you may always [ask my humans](https://github.com/greenkeeperio/greenkeeper/issues/new).Your Greenkeeper Bot :palm_tree: