Prettier 1.8:Markdown 支持
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
本次更新新增了 Markdown 支持、全新的 --insert-pragma 标志,修复了若干格式化问题,增加了对部分新实验性运算符的支持,并提升了编辑器集成体验。
重要更新
Markdown 支持
支持 Markdown (#2943) by @ikatyang
现在你可以对 Markdown 文件运行 Prettier 了!🎉
该实现高度遵循 CommonMark 规范,并基于优秀的 remark-parse 包构建。
自动换行
Prettier 的核心功能之一是按指定行宽自动折行代码。该功能同样适用于 Markdown,这意味着你可以轻松维护整洁的 80 字符宽 Markdown 文件,无需在增删文字时手动调整换行符。
输入示例:
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.
输出:
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.
注意:我们正考虑为此添加配置选项,讨论详见 #3183
更新:我们已在1.8.2版本添加--no-prose-wrap选项
CJK 用户注意:如果你的 Markdown 渲染器不支持 CJK 换行处理,需使用 markdown-it-perfect-newline-for-cjk、hexo-filter-fix-cjk-spacing 等插件移除额外空格。
// Source
一二三
四五六
七八九
// Rendered content with unsupported renderer
一二三 四五六 七八九
// Rendered content with supported renderer or via plugin
一二三四五六七八九
代码块格式化
借助 Prettier 的通用"多解析器"能力,现在可以格式化 Markdown 中的代码块!我们会根据代码块指定的语言标识确定其类型,因此能格式化 Prettier 支持的任何语言(包括嵌套的 Markdown 代码块)。
输入示例:
```js
reallyUgly (
javascript
)
```
```css
.h1 { color : red }
```
输出:
```js
reallyUgly(javascript);
```
```css
.h1 {
color: red;
}
```
注意:某些情况下你可能不希望格式化 Markdown 中的代码块。与其他语言类似,你可以在代码块前使用忽略注释来跳过格式化:
<!-- prettier-ignore -->
```js
ugly ( code ) ;
```
列表处理
调整列表项顺序后,运行 Prettier 会自动修正所有序号!

提示:若希望获得更清晰的代码差异,可通过全使用
1.作为列表标记来禁用此功能。
表格优化
表格会根据内容自动调整列宽。若没有自动化工具,这类维护工作将极其困难。
JS 中的 Markdown
通过 md 或 markdown 标签模板,可以直接格式化 JavaScript 中的 Markdown 代码。
const markdown = md`
# heading
1. list item
`;
CLI
添加向首个文档块插入 @format 的选项 (#2865) by @samouri
在 1.7 版本中,我们新增了 --require-pragma 选项,要求文件必须包含 /** @format */ 编译指示才能被格式化。现在您可以使用 --insert-pragma 标志,批量向大量文件添加此编译指示。
prettier --write "folder/**/*.js" --insert-pragma
添加 --loglevel 选项 (#2992) by @ikatyang
这个实用功能允许您按需启用(或禁用)Prettier 的日志记录。自 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/**
JavaScript
修复 JSDoc 注释的缩进问题 (#2470) by @maxdeviant
这是 Prettier 长期存在的已知问题。当格式化导致缩进级别变更的代码时,JSDoc 注释会出现错位。我们很高兴地宣布此问题现已修复!
// Before
function theFunction2(action$, store) {
/*
* comments
*/
return true;
}
// After
function theFunction2(action$, store) {
/*
* comments
*/
return true;
}
支持管道运算符和空值合并运算符 (#3036) by @azz
我们新增了对两个新提案运算符的支持:管道运算符_和_空值合并运算符。
管道运算符目前处于 stage 1 提案阶段。
该提案引入了类似 F#、OCaml、Elixir、Elm、Julia、Hack、LiveScript 以及 UNIX 管道的 |> 运算符。它通过可读的函数式风格简化链式函数调用,并提供扩展内置原型的实用替代方案。
// Before
let result = exclaim(capitalize(doubleSay("hello")));
// After
let result = "hello"
|> doubleSay
|> capitalize
|> exclaim;
空值合并运算符同样处于 stage 1 提案阶段。
当结合可选链运算符访问嵌套结构时,常需要为 null 或 undefined 的属性提供默认值。
该运算符类似 ||,但仅当左侧为 undefined 或 null 时才计算右侧值(不包含 ""、0、NaN 等情况)。
const foo = object.foo ?? "default";
优化模板字面量的表达式换行 (#3124) by @duailibe
这是 Prettier 的另一个已知问题:当模板字符串包含表达式且超出打印宽度时,会在表达式内部产生不合理的换行。现在如需插入换行,Prettier 会在 ${ 和 } 之间进行换行。
// 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`
JSX
不再内联箭头函数属性的尾部 } (#3110) by @duailibe
为更贴近 Airbnb 风格指南,且因原有打印方式并非有意设计,我们调整了 JSX 中 } 的位置至新行。这使差异对比更友好,并便于在编辑器中移动代码行。
// 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)
}
/>;
其他变更
JavaScript
改进工厂函数检测以处理多个元素 (#3112) by @vjeux
修复了 Prettier 判断表达式是否为工厂函数的启发式规则中的缺陷,现在能正确处理较长的成员表达式链。
// 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");
正确处理函数名与开括号之间的注释 (#2979) by @azz
注释定位是个永无止境的挑战 😉。本次修复确保函数名旁边的注释能被正确重新排版。
// Before
function f(/* comment*/ promise) {}
// After
function f /* comment*/(promise) {}
支持成员链中的连续调用表达式 (#2990) by @chrisvoll
成员链是 Prettier 最复杂的处理环节之一。该 PR 修复了重复调用导致后续方法无法换行的问题。
// Before
wrapper
.find("SomewhatLongNodeName")
.prop("longPropFunctionName")().then(function() {
doSomething();
});
// After
wrapper
.find("SomewhatLongNodeName")
.prop("longPropFunctionName")()
.then(function() {
doSomething();
});
考虑成员长调用链中的空行 (#3035) by @jackyho112
此前 Prettier 会删除成员链中的所有换行符。现在当源码存在换行时,我们会保留最多一个换行符。这对于需要多行展示的流式 API 非常实用。
angular
.module("AngularAppModule")
// Constants.
.constant("API_URL", "http://localhost:8080/api")
// App configuration.
.config(appConfig)
.run(appRun);
修复换行时首个参数位置错误的问题 (#3079) by @mutdmour
该问题源于我们特殊的对象内联处理机制,导致函数调用的缩进缺失。
// Before
db.collection("indexOptionDefault").createIndex({ a: 1 },
{
indexOptionDefaults: true
},
function(err) {
// code
});
// After
db.collection("indexOptionDefault").createIndex(
{ a: 1 },
{
indexOptionDefaults: true
},
function(err) {
// code
}
);
为成员表达式中的二元运算添加括号换行 (#2958) by @duailibe
同样修复了逻辑表达式缩进缺失的边缘情况。
// 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);
禁止在 NewExpression 内部断开 MemberExpression (#3075) by @duailibe
某些换行位置会导致极其怪异的格式。该修复消除了这种不合理的换行方式。
// 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
}
);
}
}
修复方法链中的数组访问器格式 (#3137) by @duailibe
在方法链中分组元素时,数组访问器应打印在组末尾而非开头。
// 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)
Flow 与 TypeScript
修复交叉对象类型的缩进问题 (#3074) by @duailibe
修复了交叉类型中细微的对齐错误。
// Before
type intersectionTest = {
propA: X
} & {
propB: X
} & {
propC: X
} & {
propD: X
};
// After
type Props = {
propA: X
} & {
propB: X
} & {
propC: X
} & {
propD: X
};
保留 ConditionalExpression 中 TSAsExpression 的括号 (#3053) by @azz
修复了 TypeScript as 断言需要保留括号但被遗漏的情况。
// Before
aValue as boolean ? 0 : -1;
// After
(aValue as boolean) ? 0 : -1;
JSX
合并多个 JSX 空白符 (#2973) by @karl
此修复解决了 JSX 格式化偶尔需要运行两次才能稳定的问题。该问题出现在存在多个 JSX 空白元素或 JSX 空白后跟空格时。
// Before
<div>
{" "} <Badge src={notificationIconPng} />
</div>;
// After
<div>
{" "}
<Badge src={notificationIconPng} />
</div>
当存在尾部注释时,不在同一行打印 JSX 括号 (#3088) by @azz
这是 --jsx-bracket-same-line 选项的问题。事实证明并非总是能在同一行放置括号...
// Input
<div
// comment
>
{foo}
</div>
// Before
<div>
// comment
{foo}
</div>;
// After
<div
// comment
>
{foo}
</div>;
CSS
保留 grid 声明中的换行符 (#3133) by @duailibe
Prettier 现在会保留源代码中的换行符,当格式化 grid 和 grid-template-* 规则时,因为保持这些规则在不同行很重要,但仍会应用与其他规则相同的格式化(例如数字和引号)。
/* 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;
}
SCSS
将 SCSS 映射格式化为类似 CSS 规则 (#3070) by @asmockler
事实证明,在多行打印 SCSS 映射会更加美观。
// Before
$map: (color: [#111111](https://github.com/prettier/prettier/pull/111111), text-shadow: 1px 1px 0 salmon)
// After
$map: (
color: [#111111](https://github.com/prettier/prettier/pull/111111),
text-shadow: 1px 1px 0 salmon
);
CSS-in-JS
修复 styled(Foo).attrs(...)`` 的格式化问题 (#3073) by @existentialism
Prettier 现在可以正确格式化如下 styled-components 代码中的 CSS:
styled(Component).attrs({})`
color: red;
`;
GraphQL
禁止格式化含表达式的 GraphQL 模板字面量 (#2975) by @duailibe
Prettier 不支持在 GraphQL 中格式化 JavaScript 表达式。详见跟踪问题 #2640。此前格式化含表达式的代码会导致无效语法,因此我们已完全禁止在 GraphQL 包含 JavaScript 表达式时进行格式化,直至完全支持该功能。
// Before
(invalid code)
// After
graphql(schema, `{ query test { id }} ${fragment}`)
CLI
当 stdout 不是 TTY 时不使用 ANSI 代码 (#2903) by @Narigo
先前将 --list-different 输出通过管道传递给其他工具时存在问题,因为我们使用 ANSI 颜色代码显示文件修改状态。此 PR 在 Prettier 输出被管道传输时禁用颜色显示。
配置
CLI 使用相对路径 (#2969) by @ahmedelgabri
修复了当 CLI 传入以 ./ 开头的路径时,无法匹配 .prettierignore 中模式的问题。
## .prettierignore
path/to/*.js
此修复后执行以下命令时不会写入任何文件:
$ prettier --write ./path/to/*.js
相对于配置文件解析文件路径 (#3037) by @azz
修复了在某些条件下,使用绝对路径时 resolveConfig API 无法正确应用 .prettierrc 覆盖配置的问题。
核心
尊重中日韩字符宽度和组合字符 (#3003, #3015) by @ikatyang
现在,中文、日文和韩文字符将被视为两个字符宽度。
// Before (exceeds print width when CJK characters are 2x monospace chars)
const x = ["中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文", "中文"];
// After
const x = [
"中文",
// ...
"中文"
];
##3015 还确保组合字符(例如 Á)被计为一个字符。
编辑器支持
实现 getSupportInfo() 并将其用于解析推断 (#3033) by @azz
我们在 API 中新增了函数 (prettier.getSupportInfo([version])),以及 CLI 标志 --support-info。这可用于查询 Prettier 当前版本或历史版本支持的语言信息。同时提供 CodeMirror IDs、tmScopes 等实用元数据,帮助文本编辑器集成自动化处理查找表的工作。
在内部实现中,我们利用这些信息驱动文件扩展名与解析器的映射关系,并支持无扩展名的常见配置文件(如 .prettierrc, Jakefile 等)。
## prettier knows that this file is JSON now.
$ prettier --write .prettierrc
根据语言拆分源代码元素 (#3069) by @CiGit
此修复解决了编辑器中进行范围格式化时,格式化对象会导致 Prettier 崩溃的问题。
致谢! ❤️
感谢所有为本次发布做出贡献的开发者,以及提出问题反馈的社区成员!Prettier 已成为广受开发者信赖的高稳定性代码格式化工具。我们高度重视这份信任,始终优先修复可能导致代码破坏的罕见问题。只有知晓问题才能解决问题,请随时创建新 issue!
