Prettier 2.6:新增 singleAttributePerLine 选项及支持最新 JavaScript 特性!
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
本次发布引入了新的 singleAttributePerLine 选项。该选项可在 Vue 单文件组件模板、HTML 和 JSX 中实现每行仅输出一个属性。根据我们的选项设计哲学,我们本不愿添加此类选项。然而大量用户需要此功能,且主流风格指南如 Airbnb JavaScript 风格指南和Vue 风格指南均推荐每行单属性的代码风格。该功能的拉取请求于 2019 年 10 月提出,其与对应议题均获得了大量用户支持。对我们而言这是艰难的决定,希望新增此选项能在不显著违背原则的前提下惠及众多用户。
我们还通过 Babel 新增了对部分 JavaScript 新语法提案的格式化支持。
致谢我们的赞助商!
如今年初的博客文章所述,我们已开始使用赞助资金向维护者支付报酬。衷心感谢所有促成此事的赞助商!特别鸣谢以下捐赠超 1000 美元的企业与个人:
如果您喜欢 Prettier 并希望支持我们的工作,欢迎通过 我们的 OpenCollective 直接赞助,或赞助我们依赖的项目,包括 typescript-eslint、remark 和 Babel。
重要更新
TypeScript
支持 TypeScript 4.6 (#12400 by @dependabot)
我们已将解析 TS 代码的 TypeScript 版本更新至 TypeScript 4.6。由于该版本未新增语法特性,我们无需进行其他调整。
HTML
强制单属性换行 (#6644 by @kankje)
新增 singleAttributePerLine 选项,用于指定 Prettier 是否强制在 HTML、Vue 和 JSX 中每行只保留单个属性。
<!-- Input -->
<div data-a="1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div data-a="1" data-b="2" data-c="3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<!-- Prettier 2.5 -->
<div data-a="1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div data-a="1" data-b="2" data-c="3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<!-- Prettier 2.6, with `{"singleAttributePerLine": false}` -->
<div data-a="1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div data-a="1" data-b="2" data-c="3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<!-- Prettier 2.6, with `{"singleAttributePerLine": true}` -->
<div data-a="1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div
data-a="1"
data-b="2"
data-c="3"
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
其他变更
JavaScript
在 Angular 中将 waitForAsync 识别为测试语句 (#11992 by @HendrikN)
// Input
test("foo bar", waitForAsync(() => {
const foo = "bar";
expect(foo).toEqual("bar")
}));
// Prettier 2.5
test(
"foo bar",
waitForAsync(() => {
const foo = "bar";
expect(foo).toEqual("bar");
})
);
// Prettier 2.6
test("foo bar", waitForAsync(() => {
const foo = "bar";
expect(foo).toEqual("bar");
}));
保留无代码块 if 语句后的行尾注释 (#12017 by @sosukesuzuki)
// Input
if (condition1) expression1; // comment A
else if (condition2) expression2; // comment B
else expression3; // comment C
// Prettier 2.5
if (condition1) expression1;
// comment A
else if (condition2) expression2;
// comment B
else expression3; // comment C
// Prettier 2.6
if (condition1) expression1; // comment A
else if (condition2) expression2; // comment B
else expression3; // comment C
使用 babel-ts 解析器时保留带括号 TS 关键字类型的注释 (#12070 by @sosukesuzuki)
// Input
let foo: (
// comment
never
);
// Prettier 2.5
Error: Comment "comment" was not printed. Please report this error!
// Prettier 2.6
let foo: // comment
never;
保留 continue/break 语句的行尾注释 (#12075 by @sosukesuzuki)
// Input
for (;;) continue // comment
;
// Prettier 2.5
Error: Comment "comment" was not printed. Please report this error!
// Prettier 2.6
for (;;)
continue; // comment
内联 JSX 中的 await 表达式 (#12088 & #12109 by @j-f1)
当参数符合内联条件时,JSX 中的 await 表达式现在会被内联处理。
// Input
{await Promise.all(
someVeryLongExpression
)}
{await (
<div>Lorem ipsum ...</div>
)}
// Prettier 2.5
{
await Promise.all(
someVeryLongExpression
)
}
{
await (
<div>Lorem ipsum ...</div>
)
}
// Prettier 2.6
{await Promise.all(
someVeryLongExpression
)}
{await (
<div>Lorem ipsum ...</div>
)}
新增 acorn 解析器 (#12172 by @fisker)
为 parser 选项新增值:acorn - 一款轻量快速、基于 JavaScript 的 JavaScript 解析器。
将 default case 后的注释保留在同一行 (#12177 by @duailibe)
在 switch 语句中,尽可能将紧跟在 default case 后的注释保留在同一行。
// Input
function read_statement() {
switch (peek_keyword()) {
case Keyword.impl: // impl<T> Growling<T> for Wolf {}
return ImplDeclaration.read();
default: // expression;
return ExpressionStatement.read();
}
}
// Prettier 2.5
function read_statement() {
switch (peek_keyword()) {
case Keyword.impl: // impl<T> Growling<T> for Wolf {}
return ImplDeclaration.read();
default:
// expression;
return ExpressionStatement.read();
}
}
// Prettier 2.6
function read_statement() {
switch (peek_keyword()) {
case Keyword.impl: // impl<T> Growling<T> for Wolf {}
return ImplDeclaration.read();
default: // expression;
return ExpressionStatement.read();
}
}
修复抽象方法中参数注释错位问题 (#12185 by @duailibe)
// Input
abstract class Foo {
abstract bar(
/** comment explaining userId param */
userId
)
}
// Prettier 2.5
abstract class Foo {
abstract bar(userId);
/** comment explaining userId param */
}
// Prettier 2.6
abstract class Foo {
abstract bar(
/** comment explaining userId param */
userId
);
}
修复类声明中父类类型转换问题 (#12222 & #12226 by @duailibe)
此修复包含两个独立问题:移动父类前的注释以及避免在父类周围添加多余括号。
// Input
class Foo extends /** @type {Type} */ (Bar) {}
// Prettier 2.5
class Foo /** @type {Type} */ extends ((Bar)) {}
// Prettier 2.6
class Foo extends /** @type {Type} */ (Bar) {}
支持正则表达式中的 Unicode 集合表示法 (#12241 by @fisker)
通过 Babel 7.17.0 现已支持 Unicode 集合表示法 的 Stage 3 提案。
请参阅 Babel v7.17.0 的发布博客文章和该提案的 README了解详细信息。在使用 Prettier 格式化此提案语法前,请务必阅读我们关于非标准语法的政策。
// Examples
/[\p{Decimal_Number}--[0-9]]/v; // Non-ASCII decimal digits
"Did you see the 👩🏿❤️💋👩🏾 emoji?".match(/\p{RGI_Emoji}/v). // ["👩🏿❤️💋👩🏾"]
/[\r\n\q{\r\n|NEWLINE}]/v; // Matches \r, \n, \r\n or NEWLINE
为带装饰器的 ClassExpression 添加括号 (#12260 by @fisker)
// Input
(@f() class {});
// Prettier 2.5
@f()
class {};
// Prettier 2.5 (Second format)
SyntaxError: A class name is required. (2:7)
1 | @f()
> 2 | class {};
| ^
3 |
// Prettier 2.6
(
@f()
class {}
);
优化 Flow 和 TS 中类型别名注释的打印方式 (#12268 by @duailibe)
在 Flow 中,注释现在将更符合我们在赋值语句(右侧为对象表达式)中的注释打印方式:
// Input
type Props = // comment explaining the props
{
isPlaying: boolean
};
// Prettier 2.5
// comment explaining the props
type Props = {
isPlaying: boolean,
};
// Prettier 2.6
type Props =
// comment explaining the props
{
isPlaying: boolean,
};
此项变更还修复了 TypeScript 中类似位置的注释在二次格式化后会被移动的问题:
// Input
type Props = // comment explaining the props
{
isPlaying: boolean
};
// Prettier 2.5
type Props = { // comment explaining the props
isPlaying: boolean;
};
// Prettier 2.5 (2nd format)
type Props = {
// comment explaining the props
isPlaying: boolean;
};
// Prettier 2.6
type Props =
// comment explaining the props
{
isPlaying: boolean,
};
支持私有字段解构 (#12276 by @sosukesuzuki)
通过 Babel 7.17 现已支持 TC39 第二阶段提案的私有字段解构。在使用 Prettier 格式化此提案语法前,请务必阅读我们关于非标准语法的政策。
// Example
class Foo {
constructor() {
console.log(this.#x); // => 1
const { #x: x } = this;
console.log(x); // => 1
}
}
支持装饰器自动访问器语法 (#12299 by @sosukesuzuki)
支持新装饰器提案引入的自动访问器语法。在使用 Prettier 格式化此提案语法前,请务必阅读我们关于非标准语法的政策。
// Example
@defineElement("my-class")
class C extends HTMLElement {
@reactive accessor clicked = false;
}
修复赋值语句中 = 符号后行注释导致的幂等问题 (#12349 by @thorn0)
// Input
const kochabCooieGameOnOboleUnweave = // !!!
rhubarbRhubarb(annularCooeedSplicesWalksWayWay);
// Prettier 2.5, first format
const kochabCooieGameOnOboleUnweave = rhubarbRhubarb( // !!!
annularCooeedSplicesWalksWayWay
);
// Prettier 2.5, second format
const kochabCooieGameOnOboleUnweave = rhubarbRhubarb(
// !!!
annularCooeedSplicesWalksWayWay
);
// Prettier 2.6
const kochabCooieGameOnOboleUnweave = // !!!
rhubarbRhubarb(annularCooeedSplicesWalksWayWay);
TypeScript
重构明确赋值断言的打印逻辑 (#12351 by @thorn0)
现在即使明确赋值断言后没有类型注解也会被打印。虽然在 TypeScript 中这是错误语法,但 TS 仍能解析此类文件。
// Input
let a!;
// Prettier 2.5
let a;
// Prettier 2.6
let a!;
为元组类型中的剩余元素添加尾部逗号 (#12390 by @sosukesuzuki)
自 TypeScript 4.2 起,元组类型中的剩余元素(...T)后允许出现普通元素。为保持一致性并减少未来在末尾元素后添加新元素时的差异,Prettier 现在会为尾部剩余元素添加尾部逗号(启用尾部逗号时)。
// { trailingCommma: "all" }
// Input
type Foo = [
Element,
Element,
Element,
Element,
Element,
Element,
...RestElement,
];
// Prettier 2.5
type Foo = [
Element,
Element,
Element,
Element,
Element,
Element,
...RestElement
];
// Prettier 2.6
type Foo = [
Element,
Element,
Element,
Element,
Element,
Element,
...RestElement,
];
Flow
修复 Flow 类声明中 static 索引器的格式化问题 (#12009 by @gkz)
// Input
declare class A {
static [string]: boolean;
}
// Prettier 2.5
declare class A {
[string]: boolean;
}
// Prettier 2.6
declare class A {
static [string]: boolean;
}
CSS
保留 SCSS 映射中的空行 (#12210 by @duailibe)
此更改同样适用于具有类似语法的一些 PostCSS 功能。
/* Input */
$colours: (
"text": $light-100,
"background-primary": $dark-300,
"background-secondary": $dark-200,
"background-tertiary": $dark-100
);
/* Prettier 2.5 */
$colours: (
"text": $light-100,
"background-primary": $dark-300,
"background-secondary": $dark-200,
"background-tertiary": $dark-100
);
/* Prettier 2.6 */
$colours: (
"text": $light-100,
"background-primary": $dark-300,
"background-secondary": $dark-200,
"background-tertiary": $dark-100
);
修复 postcss 值的小写转换问题 (#12393 by @niklasvatn)
PostCSS 的值可以以数字开头。在下面的示例中,Prettier 会将其解释为一个数字后跟一个单位。
// Input
@value 4XLarge 28/36px;
.test {
font: 4XLarge Helvetica;
}
// Prettier 2.5
@value 4XLarge 28/36px;
.test {
font: 4xlarge Helvetica;
}
// Prettier 2.6
@value 4XLarge 28/36px;
.test {
font: 4XLarge Helvetica;
}
SCSS
修复映射内的注释 (#11920 by @fisker)
// Input
.ag-theme-balham {
@include ag-theme-balham(
(
foreground-color: $custom-foreground-color,
disabled-foreground-color: null, // TODO some comment
)
);
}
// Prettier 2.5
.ag-theme-balham {
@include ag-theme-balham(
(
foreground-color: $custom-foreground-color,
disabled-foreground-color: null,
r: null, // TODO som
)
);
}
// Prettier 2.6
.ag-theme-balham {
@include ag-theme-balham(
(
foreground-color: $custom-foreground-color,
disabled-foreground-color: null,
// TODO some comment
)
);
}
修复名为 selector() 的 mixin 的参数打印问题 (#12213 by @duailibe)
/* Input */
@mixin selector($param: 'value') {
}
/* Prettier 2.5 */
@mixin selector($param: 'value) {
}
/* Prettier 2.6 */
@mixin selector($param: 'value') {
}
Vue
修复无效 v-for 导致的挂起问题 (#12113 by @fisker)
// Input
<template>
<div>
<div v-for=" a in ">aaaaa</div>
</div>
</template>
// Prettier 2.5
// Hangs
// Prettier 2.6
<template>
<div>
<div v-for=" a in ">aaaaa</div>
</div>
</template>;
允许 <template> 的 lang 属性为空 (#12394 by @HallvardMM)
模板标签应允许空字符串 lang="" 或未定义的 lang
<!-- Input -->
<template lang="">
<v-app-bar>
<v-menu offset-y>
<template></template>
</v-menu>
</v-app-bar>
</template>
<template lang>
<v-app-bar>
<v-menu offset-y>
<template></template>
</v-menu>
</v-app-bar>
</template>
<!-- Prettier 2.5 -->
SyntaxError: Unexpected closing tag "v-menu". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags (5:5)
[error] 3 | <v-menu offset-y>
[error] 4 | <template></template>
[error] > 5 | </v-menu>
[error] | ^^^^^^^^^
[error] 6 | </v-app-bar>
[error] 7 | </template>
<!-- Prettier 2.6 -->
<template lang="">
<v-app-bar>
<v-menu offset-y>
<template></template>
</v-menu>
</v-app-bar>
</template>
<template lang>
<v-app-bar>
<v-menu offset-y>
<template></template>
</v-menu>
</v-app-bar>
</template>
Ember / Handlebars
正确识别 glimmer 移除了哪些反斜杠 (#12302 by @MattTheNub)
这导致 Prettier 在每次格式化文件时都会不必要地添加反斜杠。
{{! Input }}
<p>\</p>
<p>\\</p>
<p>\\\</p>
{{! Prettier 2.5 }}
<p>\\</p>
<p>\\\</p>
<p>\\\\</p>
{{! Prettier 2.6 }}
<p>\</p>
<p>\\</p>
<p>\\\</p>
GraphQL
在 GraphQL 模式定义节点上打印描述 (#11901 by @trevor-scheer)
# Input
"""SchemaDefinition description is lost"""
schema {
query: Query
}
# Prettier 2.5
schema {
query: Query
}
# Prettier 2.6
"""
SchemaDefinition description is lost
"""
schema {
query: Query
}
YAML
修复意外删除以 U+3000 开头的块文字行的问题 (#12305 by @Quramy)
# Input
block_with_ideographic_space: |
line-content # This line starts with U+3000
# Prettier 2.5
block_with_ideographic_space: |
// Prettier 2.6
block_with_ideographic_space: |
line-content # This line starts with U+3000
CLI
新增 --no-plugin-search 选项以关闭插件自动加载 (#10274 by @fisker)
要关闭插件自动加载,在使用 Prettier CLI 时使用 --no-plugin-search 选项,或在 prettier.format() 的选项中或配置文件中添加 { pluginSearchDirs: false }。
// Prettier 2.5
$ prettier . --plugin-search-dir=a-dir-without-plugins
// Prettier 2.6
$ prettier . --no-plugin-search
为 .swcrc 推断解析器 (#12320 by @sosukesuzuki)
将 .swcrc 文件格式化为 JSON 文件。
其他改进
切换到 esbuild (#12055 by @fisker)
我们已将构建流程从 Rollup 切换至 esbuild。esbuild 速度显著提升,大幅优化了我们的开发体验。这是一项内部变更,不应影响用户。如果您在升级后遇到任何问题,请提交 issue!
