Merge branch 'v3.8.x'

# Conflicts:
#	src/language-markdown/embed.js
#	tests/format/misc/errors/front-matter/__snapshots__/format.test.js.snap
This commit is contained in:
fisker committed 2026-01-15 08:10:20 +08:00
commit 01d1469c84
13 files changed
+204 -34

No files matched your search

+1 -1
View File
@@ -26,7 +26,7 @@ Don't fill the form below manually! Let a program create a report for you:
-->
**Prettier 3.7.4**
**Prettier 3.8.0**
[Playground link](https://prettier.io/playground/#.....)
```sh
+1 -1
View File
@@ -20,7 +20,7 @@ BEFORE SUBMITTING AN ISSUE:
**Environments:**
- Prettier Version: 3.7.4
- Prettier Version: 3.8.0
- Running Prettier via: <!-- CLI, Node.js API, Browser API, etc. -->
- Runtime: <!-- Node.js v14, Chrome v83, etc. -->
- Operating System: <!-- Windows, Linux, macOS, etc. -->
+4 -2
View File
@@ -4,14 +4,16 @@ on:
push:
branches:
- main
- patch-release
- next
- v*
- patch-release
- "!renovate/**"
pull_request:
branches:
- main
- patch-release
- next
- v*
- patch-release
- "!renovate/**"
permissions:
+3 -1
View File
@@ -4,8 +4,10 @@ on:
push:
branches:
- main
- patch-release
- next
- v*
- patch-release
- "!renovate/**"
pull_request:
permissions:
+3 -1
View File
@@ -4,8 +4,10 @@ on:
push:
branches:
- main
- patch-release
- next
- v*
- patch-release
- "!renovate/**"
paths:
- "scripts/tools/eslint-plugin-prettier-internal-rules/**"
# This workflow file
+3 -1
View File
@@ -4,8 +4,10 @@ on:
push:
branches:
- main
- patch-release
- next
- v*
- patch-release
- "!renovate/**"
pull_request:
permissions:
+3 -1
View File
@@ -4,8 +4,10 @@ on:
push:
branches:
- main
- patch-release
- next
- v*
- patch-release
- "!renovate/**"
pull_request:
permissions:
+6
View File
@@ -1,3 +1,9 @@
# 3.8.0
[diff](https://github.com/prettier/prettier/compare/3.7.4...3.8.0)
🔗 [Release Notes](https://prettier.io/blog/2026/01/14/3.8.0)
# 3.7.4
[diff](https://github.com/prettier/prettier/compare/3.7.3...3.7.4)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "prettier",
"version": "3.8.0-dev",
"version": "3.9.0-dev",
"description": "Prettier is an opinionated code formatter",
"bin": "./bin/prettier.cjs",
"repository": "prettier/prettier",
@@ -179,7 +179,7 @@
"node-style-text": "2.1.2",
"npm-run-all2": "8.0.4",
"open-editor": "6.0.0",
"prettier": "3.7.4",
"prettier": "3.8.0",
"pretty-bytes": "7.1.0",
"pretty-ms": "9.3.0",
"puppeteer": "24.34.0",
+1 -1
View File
@@ -21,5 +21,5 @@ export default async function mergeBlogPost({
);
await waitForEnter();
await runGit(["pull", repo]);
await runGit(["pull", "--repo", repo]);
}
+154
View File
@@ -0,0 +1,154 @@
---
authors: "fisker"
title: "Prettier 3.8: Support for Angular v21.1"
---
We're excited to announce that Prettier now fully supports the fresh features landing in Angular v21.1 (released today 🎉)!
This update brings cleaner, more expressive templates with:
- Consecutive `@case` statements in `@switch` blocks.
- Spread elements (`...`) in array literals, object literals, and function calls inside templates.
We've also added the ability to format Angular syntax beautifully inside Markdown code blocks.
If you find Prettier valuable and want to help us keep pace with fast-moving frameworks like Angular, please consider [sponsoring us on OpenCollective](https://opencollective.com/prettier) or supporting the projects we rely on. Thank you for being part of this community — your support means a lot!
<!-- truncate -->
## Highlights
### Angular
#### Support for consecutive switch cases ([#18593](https://github.com/prettier/prettier/pull/18593) by [@fisker](https://github.com/fisker)) {#change-18593}
<!-- prettier-ignore -->
```html
<!-- Input -->
@switch (userRole) {
@case ('admin')
@case ('moderator') {
<p>Welcome, boss! Full access.</p>
}
@case ('user') { <p>Standard access</p> }
@default { <p>Guest view</p> }
}
<!-- Prettier 3.7 -->
SyntaxError: Incomplete block "case". If you meant to write the @ character, you should use the "&#64;" HTML entity instead. (2:3)
<!-- Prettier 3.8 -->
@switch (userRole) {
@case ("admin")
@case ("moderator") {
<p>Welcome, boss! Full access.</p>
}
@case ("user") {
<p>Standard access</p>
}
@default {
<p>Guest view</p>
}
}
```
#### Support for spread elements ([#18596](https://github.com/prettier/prettier/pull/18596), [#18636](https://github.com/prettier/prettier/pull/18636) by [@prettier](https://github.com/prettier)) {#change-18596}
<!-- prettier-ignore -->
```html
<!-- Input -->
<MyComponent
[array]="[ ...foo, ...bar]"
[object]="{...bar, ...extra }"
[call]="call( ...baz)"
/>
<!-- Prettier 3.7 -->
<MyComponent
[array]="[ ...foo, ...bar]"
[object]="{...bar, ...extra }"
[call]="call( ...baz)"
/>
<!-- Prettier 3.8 -->
<MyComponent
[array]="[...foo, ...bar]"
[object]="{ ...bar, ...extra }"
[call]="call(...baz)"
/>
```
## Other Changes
### Angular
#### Don't print attribute values that are single template or string literals on new lines ([#18378](https://github.com/prettier/prettier/pull/18378) by [@ravindUwU](https://github.com/ravindUwU)) {#change-18378}
<!-- prettier-ignore -->
```html
<!-- Input -->
<component
[property]="`
template
literal
`"
/>
<!-- Prettier 3.7 -->
<component
[property]="
`
template
literal
`
"
/>
<!-- Prettier 3.8 -->
<component
[property]="`
template
literal
`"
/>
```
### Markdown
#### Support formatting Angular syntax in code block ([#18519](https://github.com/prettier/prettier/pull/18519) by [@fisker](https://github.com/fisker)) {#change-18519}
<!-- prettier-ignore -->
````md
<!-- Input -->
```angular-ts
@Component({
selector: 'app-root',
template: `<div
>Welcome to {{
Angular}}! </div>`,
})
export class App {}
```
```angular-html
<div
>Welcome to {{
Angular}}! </div>
```
<!-- Prettier 3.7 -->
Same as input
<!-- Prettier 3.8 -->
```angular-ts
@Component({
selector: "app-root",
template: `<div>Welcome to {{ Angular }}!</div>`,
})
export class App {}
```
```angular-html
<div>Welcome to {{ Angular }}!</div>
```
````
@@ -21,7 +21,7 @@ Required options:
- **[`parser`](options.md#parser) (or [`filepath`](options.md#file-path))**: One of these options has to be specified for Prettier to know which parser to use.
- **`plugins`**: Unlike the `format` function from the [Node.js-based API](api.md#prettierformatsource-options), this function doesn’t load plugins automatically. The `plugins` option is required because all the parsers included in the Prettier package come as plugins (for reasons of file size). These plugins are files in [https://unpkg.com/browse/prettier@3.7.4/plugins](https://unpkg.com/browse/prettier@3.7.4/plugins). Note that `estree` plugin should be loaded when printing JavaScript, TypeScript, Flow, or JSON.
- **`plugins`**: Unlike the `format` function from the [Node.js-based API](api.md#prettierformatsource-options), this function doesn’t load plugins automatically. The `plugins` option is required because all the parsers included in the Prettier package come as plugins (for reasons of file size). These plugins are files in [https://unpkg.com/browse/prettier@3.8.0/plugins](https://unpkg.com/browse/prettier@3.8.0/plugins). Note that `estree` plugin should be loaded when printing JavaScript, TypeScript, Flow, or JSON.
You need to load the ones that you’re going to use and pass them to `prettier.format` using the `plugins` option.
@@ -32,8 +32,8 @@ See below for examples.
### Global
```html
<script src="https://unpkg.com/prettier@3.7.4/standalone.js"></script>
<script src="https://unpkg.com/prettier@3.7.4/plugins/graphql.js"></script>
<script src="https://unpkg.com/prettier@3.8.0/standalone.js"></script>
<script src="https://unpkg.com/prettier@3.8.0/plugins/graphql.js"></script>
<script>
(async () => {
const formatted = await prettier.format("type Query { hello: String }", {
@@ -50,8 +50,8 @@ Note that the [`unpkg` field](https://unpkg.com/#examples) in Prettier’s `pack
```html
<script type="module">
import * as prettier from "https://unpkg.com/prettier@3.7.4/standalone.mjs";
import * as prettierPluginGraphql from "https://unpkg.com/prettier@3.7.4/plugins/graphql.mjs";
import * as prettier from "https://unpkg.com/prettier@3.8.0/standalone.mjs";
import * as prettierPluginGraphql from "https://unpkg.com/prettier@3.8.0/plugins/graphql.mjs";
const formatted = await prettier.format("type Query { hello: String }", {
parser: "graphql",
@@ -64,8 +64,8 @@ Note that the [`unpkg` field](https://unpkg.com/#examples) in Prettier’s `pack
```js
define([
"https://unpkg.com/prettier@3.7.4/standalone.js",
"https://unpkg.com/prettier@3.7.4/plugins/graphql.js",
"https://unpkg.com/prettier@3.8.0/standalone.js",
"https://unpkg.com/prettier@3.8.0/plugins/graphql.js",
], async (prettier, ...plugins) => {
const formatted = await prettier.format("type Query { hello: String }", {
parser: "graphql",
@@ -96,8 +96,8 @@ This syntax doesn’t necessarily work in the browser, but it can be used when b
<TabItem value="module" label="Module worker">
```js
import * as prettier from "https://unpkg.com/prettier@3.7.4/standalone.mjs";
import * as prettierPluginGraphql from "https://unpkg.com/prettier@3.7.41/plugins/graphql.mjs";
import * as prettier from "https://unpkg.com/prettier@3.8.0/standalone.mjs";
import * as prettierPluginGraphql from "https://unpkg.com/prettier@3.8.01/plugins/graphql.mjs";
const formatted = await prettier.format("type Query { hello: String }", {
parser: "graphql",
@@ -110,8 +110,8 @@ const formatted = await prettier.format("type Query { hello: String }", {
```js
importScripts(
"https://unpkg.com/prettier@3.7.4/standalone.js",
"https://unpkg.com/prettier@3.7.4/plugins/graphql.js",
"https://unpkg.com/prettier@3.8.0/standalone.js",
"https://unpkg.com/prettier@3.8.0/plugins/graphql.js",
);
(async () => {
@@ -131,9 +131,9 @@ If you want to format [embedded code](options.md#embedded-language-formatting),
```html
<script type="module">
import * as prettier from "https://unpkg.com/prettier@3.7.4/standalone.mjs";
import * as prettierPluginBabel from "https://unpkg.com/prettier@3.7.4/plugins/babel.mjs";
import * as prettierPluginEstree from "https://unpkg.com/prettier@3.7.4/plugins/estree.mjs";
import * as prettier from "https://unpkg.com/prettier@3.8.0/standalone.mjs";
import * as prettierPluginBabel from "https://unpkg.com/prettier@3.8.0/plugins/babel.mjs";
import * as prettierPluginEstree from "https://unpkg.com/prettier@3.8.0/plugins/estree.mjs";
console.log(
await prettier.format("const html=/* HTML */ `<DIV> </DIV>`", {
@@ -149,10 +149,10 @@ The HTML code embedded in JavaScript stays unformatted because the `html` parser
```html
<script type="module">
import * as prettier from "https://unpkg.com/prettier@3.7.4/standalone.mjs";
import * as prettierPluginBabel from "https://unpkg.com/prettier@3.7.4/plugins/babel.mjs";
import * as prettierPluginEstree from "https://unpkg.com/prettier@3.7.4/plugins/estree.mjs";
import * as prettierPluginHtml from "https://unpkg.com/prettier@3.7.4/plugins/html.mjs";
import * as prettier from "https://unpkg.com/prettier@3.8.0/standalone.mjs";
import * as prettierPluginBabel from "https://unpkg.com/prettier@3.8.0/plugins/babel.mjs";
import * as prettierPluginEstree from "https://unpkg.com/prettier@3.8.0/plugins/estree.mjs";
import * as prettierPluginHtml from "https://unpkg.com/prettier@3.8.0/plugins/html.mjs";
console.log(
await prettier.format("const html=/* HTML */ `<DIV> </DIV>`", {
+5 -5
View File
@@ -8346,12 +8346,12 @@ __metadata:
languageName: node
linkType: hard
"prettier@npm:3.7.4":
version: 3.7.4
resolution: "prettier@npm:3.7.4"
"prettier@npm:3.8.0":
version: 3.8.0
resolution: "prettier@npm:3.8.0"
bin:
prettier: bin/prettier.cjs
checksum: 10/b4d00ea13baed813cb777c444506632fb10faaef52dea526cacd03085f01f6db11fc969ccebedf05bf7d93c3960900994c6adf1b150e28a31afd5cfe7089b313
checksum: 10/a643c62f095c2987a34cea4fceddce8dea12cc3ee024494aff690cfac22ef20be835e212b39b718c833014fd22890ae156be67b75a26e2bc9b7acde9a34d31fa
languageName: node
linkType: hard
@@ -8476,7 +8476,7 @@ __metadata:
postcss-scss: "npm:4.0.9"
postcss-selector-parser: "npm:2.2.3"
postcss-values-parser: "npm:2.0.1"
prettier: "npm:3.7.4"
prettier: "npm:3.8.0"
pretty-bytes: "npm:7.1.0"
pretty-ms: "npm:9.3.0"
puppeteer: "npm:24.34.0"