Prettier 3.5: New objectWrap option, experimentalOperatorPosition option and TS config file support!
This release includes a lot of bug fixes and the following new features:
- Support for the new
objectWrap
option - Support for the new experimental
experimentalOperatorPosition
option - Support for TypeScript configuration file
See each section for details.
If you appreciate Prettier and would like to support our work, please consider sponsoring us directly via our OpenCollective or by sponsoring the projects we depend on, such as typescript-eslint, remark, and Babel. Thank you for your continued support!
Why We Added Two New Options
This release introduces two new options. If you’re familiar with Prettier’s Option Philosophy, you might be wondering: “Why add new options?” Rest assured, these aren’t your typical options, nor do they violate our option philosophy.
As the name suggests, experimentalOperatorPosition
is experimental. We have a policy for experimental options, which means it will eventually be removed. In the future, the new behavior could become the default, or this option might be dropped entirely. If you’ve been following Prettier for a while, you may recall we once added an experimentalTernaries
option, and this follows the same approach.
objectWrap
is a bit special. For a long time, we’ve struggled with how to print multi-line objects. We haven’t yet found the perfect solution, so we’ve resorted to a semi-manual approach. For more details, see our Rationale. The current behavior isn’t ideal because the final output can vary based on how the user writes their code. To provide a more consistent format, we’ve decided to introduce the objectWrap
option.
Although this release includes two new options, we want to emphasize that we haven’t forgotten Prettier’s option philosophy. These options address specific, long-standing formatting challenges without compromising our option philosophy.
Highlights
JavaScript
Add experimental option for breaking lines before binary operators (#7111 by @btmills)
This is implemented behind the --experimental-operator-position <start|end>
flag.
When binary expressions wrap lines, start
prints the operators at the start of new lines. Placing binary operators at the beginning of wrapped lines can make the operators more prominent and easier to scan.
// Input
var a = Math.random() * (yRange * (1 - minVerticalFraction)) + minVerticalFraction * yRange - offset;
// `experimentalOperatorPosition: end` (default behavior)
var a =
Math.random() * (yRange * (1 - minVerticalFraction)) +
minVerticalFraction * yRange -
offset;
// `experimentalOperatorPosition: start`
var a =
Math.random() * (yRange * (1 - minVerticalFraction))
+ minVerticalFraction * yRange
- offset;
Implement objectWrap
config option (#16163 by @pauldraper, @sosukesuzuki)
Prettier has historically done semi-manual formatting of multi-line JavaScript object literals.
Namely, an object is kept on multiple lines if there is a newline prior to the first property, even if it could fit on a single line. See Multi-line objects for more details.
While this behavior continues to be the default, --object-wrap=collapse
instead ignores whitespace when formatting object literals.
// Input
const obj1 = {
name1: "value1", name2: "value2",
};
const obj2 = { name1: "value1",
name2: "value2",
};
// Prettier 3.4
const obj1 = {
name1: "value1",
name2: "value2",
};
const obj2 = { name1: "value1", name2: "value2" };
// Prettier 3.5 (with `--object-wrapping=collapse`)
const obj1 = { name1: "value1", name2: "value2" };
const obj2 = { name1: "value1", name2: "value2" };
API
Add support for TypeScript config files (#16828 by @itsyoboieltr & @fisker)
Added new format of configuration files:
.prettierrc.ts
.prettierrc.mts
.prettierrc.cts
prettier.config.ts
prettier.config.mts
prettier.config.cts
Note:
Currently TypeScript support in Node.js is experimental.
To make TypeScript config files work, Node.js>=22.6.0 is required and Node.js v22 requires --experimental-strip-types
.
You can run prettier with
node --experimental-strip-types node_modules/prettier/bin/prettier.cjs . --write
or
NODE_OPTIONS="--experimental-strip-types" prettier . --write
Other TS loaders should also work, but not tested, use at your own risk.
For example, with tsx
, you can
node --import tsx node_modules/prettier/bin/prettier.cjs . --write
or
tsx node_modules/prettier/bin/prettier.cjs . --write
Other Changes
JavaScript
Improve word wrapping edge cases in JSX (#16700 by @seiyab)
// Input
br_triggers_expression_break =
<div><br />
text text text text text text text text text text text {this.props.type} </div>
// Prettier 3.4
br_triggers_expression_break = (
<div>
<br />
text text text text text text text text text text text {
this.props.type
}{" "}
</div>
);
// Prettier 3.5
br_triggers_expression_break = (
<div>
<br />
text text text text text text text text text text text{" "}
{this.props.type}{" "}
</div>
);
Flow
Support const
type parameters in Flow (#16947 by @gkz)
function f<const T>(): void {}
// Prettier 3.4
// Parse error
// Prettier 3.5
function f<const T>(): void {}
CSS
Break before breaking comma separated values (#16907 by @seiyab)
/* Input */
a {
background-image:
linear-gradient(to bottom, rgb(255 255 0 / 50%), rgb(0 0 255 / 50%)),
url("catfront.png");
}
/* Prettier 3.4 */
a {
background-image: linear-gradient(
to bottom,
rgb(255 255 0 / 50%),
rgb(0 0 255 / 50%)
),
url("catfront.png");
}
/* Prettier 3.5 */
a {
background-image:
linear-gradient(to bottom, rgb(255 255 0 / 50%), rgb(0 0 255 / 50%)),
url("catfront.png");
}
Vue
Support .prop
shorthand (#16920 by @fisker)
.foo
is shorthand for v-bind:foo.prop
. See v-bind
builtin directive for details.
<!-- Input -->
<template>
<button .disabled=" a &&b ">Click!</button>
</template>
<!-- Prettier 3.4 -->
<template>
<button .disabled=" a &&b ">Click!</button>
</template>
<!-- Prettier 3.5 -->
<template>
<button .disabled="a && b">Click!</button>
</template>
Angular
Improve line breaks inside ICU blocks (#16922 by @fisker)
<!-- Input -->
<span>The author is {gender, select, male {male} female {female} other {other}}</span>
<span>The author is <span>male consectetur adipiscing elit, sed do eiusmod</span></span>
<!-- Prettier 3.4 -->
<span
>The author is {gender, select, male {male} female {female} other {other}
}</span>
<span
>The author is
<span>male consectetur adipiscing elit, sed do eiusmod</span></span
>
<!-- Prettier 3.5 -->
<span
>The author is
{gender, select, male {male} female {female} other {other}}</span
>
<span
>The author is
<span>male consectetur adipiscing elit, sed do eiusmod</span></span
>
Fix extra new line inside ICU blocks (#16922 by @fisker)
<!-- Input -->
{active, select,
true {
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp
}
false {
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp
}
}
<!-- Prettier 3.4 -->
{active, select,
true {
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp
}
false {
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp
}
}
<!-- Prettier 3.5 -->
{active, select,
true {
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp
}
false {
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp
}
}
Ember / Handlebars
Handle <style>
and <pre>
tags in Handlebars/Glimmer (#15087 by @jurgenwerk)
Markdown
U+FF5E as CJK punctuation (#16832 by @tats-u)
U+FF5E FULLWIDTH TILDE (~) is commonly used as a substitute for U+301C WAVE DASH (〜) in Windows for Japanese. Full width alphabets are less used in Markdown documents comparing to other types of documents (e.g. Microsoft Office documents), and the full width tilde is much less used as this purpose compared to full width alphabets and digits. Therefore, we can assume that the full width tilde in Markdown documents in the wild are a alternative form of the wave dash and a part of CJK punctuation.
<!-- Input (--prose-wrap=never) -->
a 字 a 字 a 字
60~
100点
60〜
100点
<!-- Prettier 3.4 -->
a 字 a 字 a 字 60~ 100点 60〜10点
<!-- Prettier 3.5 -->
a 字 a 字 a 字 60~10点 60〜100点
The first symbol between 60 and 100 in the above example is U+FF5E FULLWIDTH TILDE (~) and the second one is U+301C WAVE DASH (〜).
API
Support read config from package.json
with JSONC syntax on Bun (#17041 by @fisker)
Bun 1.2 added JSONC support in package.json
, in previous version of Prettier, it will ignore prettier
config in it. Since Prettier 3.5, we can read prettier
config from it without error.
However, since it's just a Bun feature and not supported by Node.js, it can only work when running Prettier with Bun.
Important note: Prettier uses json-stringify
parser to format package.json
file by default, to support formatting package.json
file with JSONC syntax, you need override the parser option
export default {
overrides: [
{
files: ["package.json"],
options: {
parser: "jsonc",
},
},
],
};
If you can't upgrade Prettier for some reason, you can still use JSONC syntax in package.json
, but don't put your prettier
config in it, you'll have to use another configuration file.
Miscellaneous
Use ESM entrypoint for require(ESM)
(#16958 by @tats-u)
Node.js 22.12 or later can (experimentally) load ESM modules with require
function without runtime flags. This change enables require
to load Prettier without the CommonJS entrypoint with almost only the ability to import the ESM entrypoint.
The feature to load ES modules with require
is not completely stable but can be used without ExperimentalWarning as of Node 22.13.