diff --git a/changelog_unreleased/blog-post-intro.md b/changelog_unreleased/blog-post-intro.md new file mode 100644 index 000000000..c80ebff3b --- /dev/null +++ b/changelog_unreleased/blog-post-intro.md @@ -0,0 +1,15 @@ +--- +author: "Sosuke Suzuki (@sosukesuzuki)" +authorURL: "https://github.com/sosukesuzuki" +title: "Prettier 3.2: Support JSONC and Angular’s ICU expression" +--- + +This release includes new features such as adding a JSONC parser, adding Angular’s ICU expressions, and many bug fixes. + +We are still seeking feedback for the `--experimental-ternaries` option released in Prettier 3.1. Please read [A curious case of the ternaries](https://prettier.io/blog/2023/11/13/curious-ternaries) and respond via the Google Forms link provided. + +Additionally, we recommend reading [Prettier's CLI: A Performance Deep Dive](https://prettier.io/blog/2023/11/30/cli-deep-dive) by [Fabio Spampinato](https://github.com/fabiospampinato). This faster CLI is slated to be released as version 4.0. + + + +If you appreciate Prettier and would like to support our work, please consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, such as [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). Thank you for your continued support! diff --git a/website/blog/2024-01-12-3.2.0.md b/website/blog/2024-01-12-3.2.0.md new file mode 100644 index 000000000..70558a940 --- /dev/null +++ b/website/blog/2024-01-12-3.2.0.md @@ -0,0 +1,387 @@ +--- +author: "Sosuke Suzuki (@sosukesuzuki)" +authorURL: "https://github.com/sosukesuzuki" +title: "Prettier 3.2: Support JSONC and Angular’s ICU expression" +--- + +This release includes new features such as adding a JSONC parser, adding Angular’s ICU expressions, and many bug fixes. + +We are still seeking feedback for the `--experimental-ternaries` option released in Prettier 3.1. Please read [A curious case of the ternaries](https://prettier.io/blog/2023/11/13/curious-ternaries) and respond via the Google Forms link provided. + +Additionally, we recommend reading [Prettier's CLI: A Performance Deep Dive](https://prettier.io/blog/2023/11/30/cli-deep-dive) by [Fabio Spampinato](https://github.com/fabiospampinato). This faster CLI is slated to be released as version 4.0. + + + +If you appreciate Prettier and would like to support our work, please consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, such as [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). Thank you for your continued support! + +## Highlights + +### JSON + +#### New `jsonc` parser added ([#15831](https://github.com/prettier/prettier/pull/15831) by [@fisker](https://github.com/fisker)) + +Previously, we infer the parser of `.jsonc` files to be `json`, but if we want keep the trailing comma, we'll have to use a hacky workaround config `{parser: "json5", quoteProps: "preserve", singleQuote: false}`. + +The new added `jsonc` parser: + +- Always quote the object keys. +- Wrap strings with double quotes. +- Of course, respect the [`trailingComma`](https://prettier.io/docs/en/options#trailing-commas) option. + +### Angular + +#### Support formatting for Angular ICU expression ([#15777](https://github.com/prettier/prettier/pull/15777) by [@sosukesuzuki](https://github.com/sosukesuzuki)) + +Support two kinds of Angular ICU expressions: [`plural`](https://angular.dev/guide/i18n/translation-files#translate-plurals) and [`select`](https://angular.dev/guide/i18n/translation-files#translate-alternate-expressions). + + +```html + + Updated: + {minutes, plural, + =0 {just now} + =1 {one minute ago} + other {{{minutes}} minutes ago} + } + + + + The author is {gender, select, male {male} female {female} other {other}} + +``` + +## Other Changes + +### JavaScript + +#### Avoid introducing linebreaks in template interpolations ([#15209](https://github.com/prettier/prettier/pull/15209) by [@bakkot](https://github.com/bakkot)) + +In a template string like + + +```js +`this is a long message which contains an interpolation: ${format(data)} <- like this`; +``` + +avoid adding a linebreak when formatting the expression unless one is already present or it's unavoidable due to e.g. a nested function. Previously a linebreak could be introduced whenever some interpolation in the template was sufficiently "not simple": + + +```js +`this is a long message which contains an interpolation: ${format( + data, +)} <- like this`; +``` + +Now it will instead be left alone. + +If a linebreak is already present within the `${...}`, format as normal. + +#### Fix non-idempotent formatting of method chain with empty line ([#15522](https://github.com/prettier/prettier/pull/15522) by [@seiyab](https://github.com/seiyab)) + + +```js +// Input +Foo.a() + +.b(); + +// Prettier 3.1 (first format) +Foo.a() +.b(); + +// Prettier 3.1 (second format) +Foo.a().b(); + + +// Prettier 3.2 +Foo.a() + + .b(); +``` + +#### Fix formatting of ternary in function call ([#15677](https://github.com/prettier/prettier/pull/15677) by [@fisker](https://github.com/fisker)) + + +```jsx +// Input +stopDirectory = await (useCache + ? memoizedFindProjectRoot + : findProjectRootWithoutCache)(path.dirname(path.resolve(filePath))); + +// Prettier 3.1 +stopDirectory = await (useCache + ? memoizedFindProjectRoot + : findProjectRootWithoutCache)(path.dirname(path.resolve(filePath))); + +// Prettier 3.2 +stopDirectory = await ( + useCache ? memoizedFindProjectRoot : findProjectRootWithoutCache +)(path.dirname(path.resolve(filePath))); +``` + +#### Fix inconsistencies for optional-chaining ([#15806](https://github.com/prettier/prettier/pull/15806) by [@fisker](https://github.com/fisker)) + +Only happens when using `typescript`, `meriyah` or other ESTree parsers except `babel`. + + +```js +// Input +function someFunctionName() { + return isEqual(a.map(([t, _]) => t?.id), b.map(([t, _]) => t?.id)); + return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id)); +} +theValue = Object.entries(someLongObjectName).filter( + ([listingId]) => someListToCompareToHere.includes(listingId), +); +theValue = Object.entries(someLongObjectName).filter( + ([listingId]) => someListToCompareToHere?.includes(listingId), +); + +// Prettier 3.1 +function someFunctionName() { + return isEqual( + a.map(([t, _]) => t?.id), + b.map(([t, _]) => t?.id), + ); + return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id)); +} +theValue = Object.entries(someLongObjectName).filter(([listingId]) => + someListToCompareToHere.includes(listingId), +); +theValue = Object.entries(someLongObjectName).filter( + ([listingId]) => someListToCompareToHere?.includes(listingId), +); + +// Prettier 3.2 +function someFunctionName() { + return isEqual( + a.map(([t, _]) => t?.id), + b.map(([t, _]) => t?.id), + ); + return isEqual( + a?.map(([t, _]) => t?.id), + b?.map(([t, _]) => t?.id), + ); +} +theValue = Object.entries(someLongObjectName).filter(([listingId]) => + someListToCompareToHere.includes(listingId), +); +theValue = Object.entries(someLongObjectName).filter(([listingId]) => + someListToCompareToHere?.includes(listingId), +); +``` + +#### Fix comments in `if` ([#15826](https://github.com/prettier/prettier/pull/15826) by [@fisker](https://github.com/fisker)) + + +```js +// Input +if (foo) for (i = 2; i > 0; i--) console.log(i); // comment 1 +else bar(); + +for (;;){ + if (foo) continue; // comment 2 + else bar(); +} + +// Prettier 3.1 +Error: Comment "comment 2" was not printed. Please report this error! + +// Prettier 3.2 +if (foo) + for (i = 2; i > 0; i--) console.log(i); // comment 1 +else bar(); + +for (;;) { + if (foo) + continue; // comment 2 + else bar(); +} +``` + +### TypeScript + +#### Improve conditional type alias layout ([#15811](https://github.com/prettier/prettier/pull/15811) by [@seiyab](https://github.com/seiyab)) + + +```ts +// Input +type FallbackFlags = + Equals["flags"], {}> extends true + ? Dict + : NonNullableFlag["flags"]; + +// Prettier 3.1 +type FallbackFlags = Equals< + NonNullableFlag["flags"], + {} +> extends true + ? Dict + : NonNullableFlag["flags"]; + +// Prettier 3.2 +type FallbackFlags = + Equals["flags"], {}> extends true + ? Dict + : NonNullableFlag["flags"]; +``` + +### HTML + +#### Fix formatting of prettier-ignored unclosed elements ([#15748](https://github.com/prettier/prettier/pull/15748) by [@fisker](https://github.com/fisker)) + + +```html + + +

+Hello world! + + + +

+ + + +

+Hello world! +``` + +### Angular + +#### Fix `prettier-ignore`d angular control flow block ([#15827](https://github.com/prettier/prettier/pull/15827) by [@fisker](https://github.com/fisker)) + + +```html + + +@if (condition) { + Foo +} @else { + Other +} + + + +@if (condition) { + Foo +} +} @else { + Other +} + + + +@if (condition) { + Foo +} +@else { + Other +} +``` + +#### Avoid adding colon for `track` in 3rd expression of `for` blocks ([#15887](https://github.com/prettier/prettier/pull/15887) by [@sosukesuzuki](https://github.com/sosukesuzuki)) + + +```html + +@for (item of items; let i = $index; track block) {} + + +@for (item of items; let i = $index; track: block) {} + + +@for (item of items; let i = $index; track block) {} +``` + +### Ember / Handlebars + +#### Preserve path literal segments ([#15605](https://github.com/prettier/prettier/pull/15605) by [@maxpowa](https://github.com/maxpowa)) + +Fixes scenarios where an input handlebars file containing literal segments would be reformatted to unwrap the literal segments, causing syntax errors in the resulting output. + + +```hbs + +{{input.[funky +{{input.funky +{{input.[funky +```gql +# Input +union SearchResult = Conference| Festival | Concert | Venue | Conference| Festival | Concert | Venue + +# Prettier 3.1 +union SearchResult = + Conference + | Festival + | Concert + | Venue + | Conference + | Festival + | Concert + | Venue + +# Prettier 3.2 +union SearchResult = + | Conference + | Festival + | Concert + | Venue + | Conference + | Festival + | Concert + | Venue +``` + +### API + +#### Support absolute path as plugin in config file ([#15666](https://github.com/prettier/prettier/pull/15666) by [@fisker](https://github.com/fisker)) + +```js +// prettier.config.cjs +module.exports = { + plugins: [ + // posix style + "/path/to/plugin.js", + // Windows style + "D:\\\\path\\to\\plugin.js", + // Use `require.resolve` + require.resolve("my-awesome-prettier-plugin"), + ], +}; +``` + +#### Fix `getFileInfo` and `getSupportInfo` type definitions ([#15854](https://github.com/prettier/prettier/pull/15854) by [@auvred](https://github.com/auvred)) + +```ts +const plugin: Plugin = {}; + +prettier.getFileInfo("./file.ext", { + plugins: [plugin], +}); + +prettier.getSupportInfo({ plugins: [plugin], showDeprecated: true }); +``` + +### Miscellaneous + +#### Fix false claim in docs that cursorOffset is incompatible with rangeStart/rangeEnd ([#15750](https://github.com/prettier/prettier/pull/15750) by [@ExplodingCabbage](https://github.com/ExplodingCabbage)) + +The cursorOffset option has in fact been compatible with rangeStart/rangeEnd for over 5 years, thanks to work by @ds300. However, Prettier's documentation (including the CLI `--help` text) continued to claim otherwise, falsely. The documentation is now fixed.