惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

Prettier Blog

Prettier 3.8: Support for Angular v21.1 Prettier 3.7: Improved formatting consistency and new plugin features! Prettier 3.6: Experimental fast CLI and new OXC and Hermes plugins! Prettier 3.5: New objectWrap option, experimentalOperatorPosition option and TS config file support! Prettier 3.3: New Flow features and a lot of bug fixes Prettier 3.2: Support JSONC and Angular’s ICU expression Prettier's CLI: A Performance Deep Dive $20k Bounty was Claimed! Prettier 3.1: New experimental ternaries formatting and Angular control flow syntax! A curious case of the ternaries Prettier 3.0: Hello, ECMAScript Modules! Prettier 2.8: improve --cache CLI option and TypeScript 4.9 satisfies operator! Prettier 2.7: new --cache CLI option and TypeScript 4.7 syntax! Prettier 2.6: new singleAttributePerLine option and new JavaScript features! Prettier begins paying maintainers Prettier 2.5: TypeScript 4.5 and MDX v2 comment syntax! Prettier 2.4: new bracketSameLine option and TypeScript 4.4 support! Prettier 2.3. In which assignments are consistent, short keys non-breaking, and Handlebars official Prettier for Ruby goes v1.0 🎉
Prettier 3.4: A lot of bug fixes
Sosuke Suzuki · 2024-11-26 · via Prettier Blog

This release includes numerous bug fixes and other improvements.

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!

Other Changes

JavaScript

Fix template literal print with array (#13315 by @fisker, @syi0808)

// Input

const string = `${[[1, 2], [3, 4]]}`

// Prettier 3.3

const string = `${[

[2],

[4],

]}`;

// Prettier 3.4

const string = `${[

[1, 2],

[3, 4],

]}`;

Add missing parentheses in tagged template literals (#16500 by @syi0808)

// Input

(String?.raw)``;

(getTag?.())``;

// Prettier 3.3

String?.raw``;

getTag?.()``;

// Prettier 3.4

(String?.raw)``;

(getTag?.())``;

Don't remove useless \ in string literals (#16563 by @sosukesuzuki, #16763 by @fisker)

Previously, Prettier would remove useless escape characters (\) from string literals. However, this behavior was inconsistent as it did not apply to template literals, which was reported in issue #16542.

This issue is a feature request to extend this behavior to template literals as well.

After discussing this internally, the Prettier team concluded that removing useless escape characters, whether in string literals or template literals, is the responsibility of a linter, not a formatter.

This change disables the removal of useless escape characters in string literals across all languages supported by Prettier. To keep the previous behavior, we recommend using ESLint rules like no-useless-escape.

Escaped quotes (e.g. "\"\'") may get unescaped when changing between different quotes. This is explained on the Rationale page of the official documentation.

// Input

const str = "\a";

// Prettier 3.3

const str = "a";

// Prettier 3.4

const str = "\a";

// Input

!(

cond1 || // foo

cond2 || // bar

cond3 // baz

);

// Prettier 3.3

!(

(

cond1 || // foo

cond2 || // bar

cond3

) // baz

);

// Prettier 3.4

!(

cond1 || // foo

cond2 || // bar

cond3 // baz

);

Removed support for experimental syntax (#16643, #16705 by @fisker)

TypeScript

Add missing parentheses in tagged template literals (#16500 by @syi0808)

// Input

(String?.raw!)``;

(String?.raw)!``;

// Prettier 3.3

String?.raw!``;

String?.raw!``;

// Prettier 3.4

(String?.raw)!``;

(String?.raw)!``;

Preserve a comment on between decorator and modified parameter property (#16574 by @sosukesuzuki)

The current version of Prettier unexpectedly moves a line comment between a parameter property modified by readonly, private, public, etc and a decorator. This output results in invalid TypeScript code.

This change ensures that the original format is preserved.

// Input

class Foo {

constructor(

@decorator

// comment

readonly foo,

) {}

}

// Prettier 3.3

class Foo {

constructor(

@decorator

readonly // comment

foo,

) {}

}

// Prettier 3.4

class Foo {

constructor(

@decorator

// comment

readonly foo,

) {}

}

Preserve a comment between modifier and the decorated property name (#16578 by @sosukesuzuki)

There was a bug where block comments between the modifier and the name of a decorated property were being treated as trailing comments of the decorator. This behavior was not only unexpected but also lacked idempotency.

With this change, the position of the block comment between the modifier and the property name is preserved.

// Input

class Foo {

@decorator

readonly /* comment */ propertyName;

}

// Prettier 3.3

class Foo {

@decorator /* comment */

readonly propertyName;

}

// Prettier 3.3 (second output)

class Foo {

@decorator /* comment */ readonly propertyName;

}

// Prettier 3.4

class Foo {

@decorator

readonly /* comment */ propertyName;

}

There was a bug where an extra line was inserted when assigning a chained arrow function with type parameters to a variable if there was a line comment above it.

This change ensures that the extra line is no longer inserted.

// Input

const foo1 =

// comment

<T,>() => () => 1;

// Prettier 3.3

const foo1 =

// comment

<T,>() =>

() =>

1;

// Prettier 3.4

const foo1 =

// comment

<T,>() =>

() =>

1;

Support "Top-level await statements" (#16729 by @fisker)

// Input

(await (await fetch()).json()).foo

// Prettier 3.3

await(await fetch()).json().foo;

// Prettier 3.4

(await (await fetch()).json()).foo;

Fix class heritage breaks even though it remains inside the line width (#16730 by @fisker)

// Input

export class JiraCreatePixFraudDetectionGateway

implements Pick<IssuePixFraudDetectionGateway, "createPixFraudDetectionIssue">

{

constructor(private readonly logger: Logger) {

this.logger = logger.child({

context: JiraCreatePixFraudDetectionGateway.name,

});

}

}

// Prettier 3.3

export class JiraCreatePixFraudDetectionGateway

implements

Pick<IssuePixFraudDetectionGateway, "createPixFraudDetectionIssue">

{

constructor(private readonly logger: Logger) {

this.logger = logger.child({

context: JiraCreatePixFraudDetectionGateway.name,

});

}

}

// Prettier 3.4

export class JiraCreatePixFraudDetectionGateway

implements Pick<IssuePixFraudDetectionGateway, "createPixFraudDetectionIssue">

{

constructor(private readonly logger: Logger) {

this.logger = logger.child({

context: JiraCreatePixFraudDetectionGateway.name,

});

}

}

// Input

class A {

declare private readonly name: string;

}

// Prettier 3.3

class A {

private declare readonly name: string;

}

// Prettier 3.4

class A {

declare private readonly name: string;

}

CSS

Resolve some types of overrun in CSS (#16570 by @seiyab)

/* Input */

@media (prefers-reduced-data: no-preference) {

@font-face {

unicode-range: U+0000-00FF, U+0131,

U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;

}

}

/* Prettier 3.3 */

@media (prefers-reduced-data: no-preference) {

@font-face {

unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,

U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212,

U+2215, U+FEFF, U+FFFD;

}

}

/* Prettier 3.4 */

@media (prefers-reduced-data: no-preference) {

@font-face {

unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,

U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,

U+2212, U+2215, U+FEFF, U+FFFD;

}

}

This change fixes a bug where extra indentation was added when line breaks were included in the argument list of pseudo-class functions like :where(), :is(), and :not.

/* Input */

:where(input:not([type="button"], [type="reset"], [type="submit"]), textarea, select) {

/* CSS here */

}

/* Prettier 3.3 */

:where(

input:not([type="button"], [type="reset"], [type="submit"]),

textarea,

select

) {

/* CSS here */

}

/* Prettier 3.4 */

:where(

input:not([type="button"], [type="reset"], [type="submit"]),

textarea,

select

) {

/* CSS here */

}

When formatting CSS value comments, the trailing / may be lost, resulting in an invalid comment.

This change ensures that value comments are not truncated.

/* Input */

h1 {

--OFF: /* OFF */;

}

/* Prettier 3.3 */

h1 {

--OFF: /* OFF *;

}

/* Prettier 3.4 */

h1 {

--OFF: /* OFF */;

}

SCSS

Fix error thrown when formatting SCSS file (#16607 by @fisker)

// Input

@if true {

$newKey: ($key: ( $theme-name: $value ))

}

// Prettier 3.3

Error

// Prettier 3.4

@if true {

$newKey: (

$key:

(

$theme-name: $value,

),

);

}

/* Input */

$z-indexes: (

header: 1035,

overlay: 1202 // TODO: change to 1050 after bootstrap modals will be removed

);

/* Prettier 3.3 */

$z-indexes: (

header: 1035,

overlay: 1202 // TODO: change to 1050 after bootstrap modals will be removed,

);

/* Prettier 3.4 */

$z-indexes: (

header: 1035,

overlay: 1202, // TODO: change to 1050 after bootstrap modals will be removed

);

HTML

Keep doctype in non-html files unchanged (#16765 by @fisker)

In Prettier v3, we print HTML5 doctype in lowercase, it's safe for HTML files, however users may use the html parser to format other files eg: XHTML files, lowercase the doctype will break XHTML documents.

Starting with Prettier 3.4, we'll only lowercase HTML5 doctype (<!doctype html>) when the file extension is .html or .htm, otherwise they will be untouched.

<!-- Input -->

<!-- foo.xhtml -->

<!DOCTYPE html>

<!-- Prettier 3.3 -->

<!doctype html>

<!-- Prettier 3.4 -->

<!DOCTYPE html>

Vue

<!-- Input -->

<template>

<button @click="点击事件">点击!</button>

<button @click="onClick">Click!</button>

</template>

<!-- Prettier 3.3 -->

<template>

<button @click="点击事件;">点击!</button>

<button @click="onClick">Click!</button>

</template>

<!-- Prettier 3.4 -->

<template>

<button @click="点击事件">点击!</button>

<button @click="onClick">Click!</button>

</template>

Angular

Support Angular 19 (#16862 by @fisker)

Angular 19 added support for typeof keyword in template expressions.

<!-- Input -->

<div>{{ typeof

x ===

'object' ? 'Y' : 'N'}}</div>

<!-- Prettier 3.3 -->

<div>

{{ typeof

x ===

'object' ? 'Y' : 'N'}}

</div>

// Prettier 3.4

<div>{{ typeof x === "object" ? "Y" : "N" }}</div>

Markdown

Remove excessive spaces after line prefixes for unordered lists in Markdown (#15526 by @TomasLudvik)

<!-- Input -->

- first line

- second line indented

- third line

- fourth line

- fifth line

<!-- Prettier 3.3 -->

- first line

- second line indented

- third line

- fourth line

- fifth line

<!-- Prettier 3.4 -->

- first line

- second line indented

- third line

- fourth line

- fifth line

Fix incorrect wrap in sentence with linkReference (#16546 by @seiyab)

<!-- Input (--prose-wrap=always) -->

This folder has [VHS] tape files to create gifs for the [Widget Showcase]. To run them, install VHS from main (the theme and screenshot commands are not yet released).

<!-- Prettier 3.3 -->

This folder has [VHS] tape files to create gifs for the [Widget Showcase]. To run

them, install VHS from main (the theme and screenshot commands are not yet released).

<!-- Prettier 3.4 -->

This folder has [VHS] tape files to create gifs for the [Widget Showcase]. To

run them, install VHS from main (the theme and screenshot commands are not yet

released).

Preserve non-ASCII whitespaces at the end of the line and beginning of the next line (#16619 by @tats-u)

Prettier removes non-ASCII spaces at the end of the line and beginning of the next line. However, this behavior is not consistent with the CommonMark spec.

https://spec.commonmark.org/0.31.2/#soft-line-breaks

Spaces at the end of the line and beginning of the next line are removed:

https://spec.commonmark.org/0.31.2/#unicode-whitespace-character

A Unicode whitespace character is a character in the Unicode Zs general category, or a tab (U+0009), line feed (U+000A), form feed (U+000C), or carriage return (U+000D).

Unicode whitespace is a sequence of one or more Unicode whitespace characters.

A space is U+0020.

The CommonMark spec doesn't mention non-ASCII spaces here, so removing them changes the content of the Markdown document.

<!-- Input -->

 EM Space (U+2003) EM Space

 全角スペース (U+3000) 全形空白

<!-- Prettier 3.3 -->

EM Space (U+2003) EM Space

全角スペース (U+3000) 全形空白

<!-- Prettier 3.4 -->

 EM Space (U+2003) EM Space

 全角スペース (U+3000) 全形空白

Don't break a line a between Chinese or Japanese and others (#16691 by @tats-u)

Markdown documents are mainly converted to HTML or components of JavaScript-based frameworks. This means that paragraphs in Markdown are eventually processed by the browser according to CSS rules. This is because many Markdown converter preserve line breaks in paragraphs in input Markdown and HTML itself does not specify how browsers should handle line breaks in text in HTML.

According to CSS rules (CSS Text Module Level 3 or later), browsers should remove line breaks between Chinese/Japanese characters instead of replacing them with spaces. However, this rule has been ignored by WebKit-based or Webkit-derived browsers (Chrome, Safari, and so on) for long time.

For example, the following HTML paragraph:

generated from the following Markdown:

should be rendered as follows according to CSS rules and actually is rendered such by Firefox:

However, Chrome and Safari render it as follows:

This is why we should stop Prettier from line breaking between Chinese/Japanese characters. We decided to stop Prettier from forcing users to use a plugin for a Markdown converter that concatenates lines that start or end with Chinese/Japanese characters (remark-join-cjk-lines, for example).

Also, a line break between Chinese/Japanese and others are equivalent to a space according to before the commit suspending a concrete rule in CSS Text Module Level 3 by commenting it out fixing an issue on the CSS Working Group Editor Drafts. Firefox follows this rule. Therefore, all browsers render the following paragraph:

<!-- prettier-ignore -->

```html

<p>日本語 English 汉语 한국어 漢語</p>

<p></p>

as follows:

However, Prettier has broken a line between Chinese/Japanese characters in Markdown for a long time, and between Chinese/Japanese and latin characters in some cases since 3.0.0. For example, the following Markdown paragraph:

is formatted as follows if --prose-wrap is set to the other value than preserve in Prettier 3.x:

However, the following HTML, which is generated by a Markdown-to-HTML converter based on the above Markdown:

<p>

日本語English汉语

English

漢語

</p>

is rendered as follows by all browsers:

This is why we should stop Prettier from line breaking al so around Chinese/Japanese characters in Markdown. We are going to conform Prettier's behavior to this rule in a future version. After that, line breaks between Chinese/Japanese and others will be allowed again under certain rules.

One of the few exceptions is spaces and line breaks between Chinese/Japanese and Korean letters. The following Markdown paragraphs are equivalent even in the current Prettier version:

You get the former if you format the latter with --prose-wrap=always and a sufficiently long --print-width value or with --prose-wrap=never, and you get the latter if you format the former with --prose-wrap=always with a extremely short --print-width value. Therefore, we do not have to touch such spaces and line breaks.

Another exception is those between a Chinese/Japanese character and a meaningful symbol in Markdown like *, `, [, and ]. For example, the following Markdown paragraph is equivalent even in the current Prettier version:

**Yarn** のCLI経由でフォーマットするには `yarn prettier -w ` を実行してください。

**Yarn**

のCLI経由でフォーマットするには

`yarn prettier -w .`

を実行してください。

<!-- Input (--prose-wrap=always --print-width=20) -->

日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어

日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어

<!-- Prettier 3.3 -->

日本語 汉语 漢語

English 한국어 日本

語 汉语 漢語 English

한국어 日本語 汉语

漢語 English 한국어

日本語 汉语 漢語

English 한국어

日本語汉语漢語

English한국어日本語

汉语漢語

English한국어日本語

汉语漢語

English한국어日本語

汉语漢語

English한국어

<!-- Prettier 3.4 -->

日本語 汉语 漢語 English

한국어

日本語 汉语 漢語 English

한국어

日本語 汉语 漢語 English

한국어

日本語 汉语 漢語 English

한국어

日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어

Tell regexp-util to generate regex compatible with u flag (#16816 by @tats-u)

CJK characters outside of BMP and Ideographic Variation Sequences (IVS; variation selectors dedicated for han/kanji), which consume 2 characters in JavaScript string, have not been treated as CJK. This is due to the fact that Prettier has not passed the appropriate flag "u" to the regexp-util package.

In the following example, “𠮷” (U+20BB7) is out of BMP, and “葛󠄀” is a combination of a han “葛” (U+845B) in BMP and an IVS U+E0100. The latter requires a font with the support of Adobe Japan-1 (e.g. Yu Gothic UI and Source Han Sans) to be rendered as a form different from that of the character without IVS (葛).

<!-- Input (--prose-wrap=never) -->

a 字 a 字 a 字

𠮷

𠮷

葛󠄀

葛󠄀


<!-- Prettier 3.3 -->

a 字 a 字 a 字 𠮷 𠮷 葛󠄀 葛󠄀 終

<!-- Prettier 3.4 -->

a 字 a 字 a 字𠮷𠮷葛󠄀葛󠄀終

YAML

# Input

123: # hello

# comment

# Prettier 3.3

123:# hello

# comment

# Prettier 3.4

123: # hello

# comment

API

Stop doc mutation in prettier.doc.printDocToString (#13315 by @fisker)

For performance reason, prettier.doc.printDocToString used to mutate .parts of the fill command during print. It was converted to a pure function to ensure output correctness.

Make getPreferredQuote public (#16567 by @sosukesuzuki)

This change makes the internal getPreferredQuote function a part of the public API.

In languages like JavaScript, both single quotes and double quotes can be used for string literals. Prettier determines the quote to enclose a string literal based on the number of quotes within the string and the value of the singleQuote option. For more details, please refer to the Rationale page.

The getPreferredQuote function determines the appropriate quote to enclose a string literal and has the following interface:

type Quote = '"' | "'";

function getPreferredQuote(

text: string,

preferredQuoteOrPreferSingleQuote: Quote | boolean,

): Quote;

Here are some examples of how to use it:

import * as prettier from "prettier";

const SINGLE_QUOTE = `'`;

const DOUBLE_QUOTE = `"`;

console.log(prettier.util.getPreferredQuote(`Hello World Test`, SINGLE_QUOTE)); // '

console.log(prettier.util.getPreferredQuote(`Hello World Test`, DOUBLE_QUOTE)); // "

console.log(prettier.util.getPreferredQuote(`'Hello' "World" 'Test'`, SINGLE_QUOTE)); // "

console.log(prettier.util.getPreferredQuote(`"Hello" 'World' "Test"`, DOUBLE_QUOTE)); // '

console.log(prettier.util.getPreferredQuote(`"Hello" "World" "Test"`, SINGLE_QUOTE)); // '

console.log(prettier.util.getPreferredQuote(`'Hello' 'World' 'Test'`, DOUBLE_QUOTE)); // "

Making this function public will benefit plugin developers. Since the function is relatively short, you can find more details in the implementation.

Fix loading ESM-style shared config file in Node.js 23 (#16857 by @sosukesuzuki)

In Prettier 3.3, attempting to load an ESM-style shared config file in Node.js 23 resulted in the following warnings, preventing the options from being loaded:

[warn] Ignored unknown option { __esModule: true }.

[warn] Ignored unknown option { default: { trailingComma: "es5", tabWidth: 4, singleQuote: true } }.

This issue was caused by a new module feature in Node.js 23, known as require(ESM). Prettier 3.4 resolves this problem, allowing the options to load correctly.

For more details, please see https://github.com/prettier/prettier/issues/16812.

CLI

Ignore files in the Jujutsu directory (#16684 by @marcusirgens)

The Jujutsu VCS uses the .jj directory, similarly to how Git uses .git.

This change adds .jj to the list of directories which are silently ignored by prettier.

Miscellaneous

Fix cursorOffset feature sometimes being catastrophically slow (#15709 by @ExplodingCabbage)

Previously, Prettier's cursorOffset feature would be spectacularly slow in certain unfortunate circumstances (namely when the user's cursor was not contained within a leaf node of the AST, and the non-leaf node containing it was very large and being significantly reformatted by Prettier). As a consequence, if you used Prettier via an editor integration that used cursorOffset under the hood, your editor would sometimes inexplicably hang when you tried to format a file.

All examples of this phenomenon that we are aware of should now be fixed, but bug reports of any further pathological examples would be welcome.