website/blog/2025-06-23-3.6.0.md
This release includes several important feature additions that we're excited to share with you.
First, we're shipping a new experimental high-performance CLI behind a feature flag (--experimental-cli). This CLI was previously only available in prettier@next, but now you can enable it simply by using a flag. We encourage you to try it out and share your feedback! If you are interested in the internal implementation, please read Prettier's CLI: Performance Deep Dive by Fabio.
Additionally, we're releasing two new official plugins: @prettier/plugin-oxc and @prettier/plugin-hermes. These plugins are provided separately from Prettier's core.
We want to extend our heartfelt gratitude to everyone who made this amazing release possible: @fabiospampinato, @43081j, and @pralkarz along with the new CLI contributors, @boshen and @overlookmotel along with other OXC contributors, the Flow and Hermes teams at Meta. Thank you all for your incredible contributions!
We're excited to see how these new features enhance your development experience. Happy formatting!
<!-- truncate -->You may have already heard of or used our new performance improved CLI. From Prettier 3.6, you can now use it without installing unstable v4 version.
# Run CLI with `--experimental-cli`
prettier . --check --experimental-cli
# Or use environment variable `PRETTIER_EXPERIMENTAL_CLI=1`
PRETTIER_EXPERIMENTAL_CLI=1 prettier . --check
@prettier/plugin-oxc (#17472, #17483 by @fisker) {#change-17472}@prettier/plugin-oxc is based on OXC(A fast JavaScript and TypeScript parser in Rust).
This plugin includes two new parsers oxc (JavaScript syntax) and oxc-ts (TypeScript syntax), to use this plugin:
Install the plugin
yarn add --dev prettier @prettier/plugin-oxc
Add the following to your .prettierrc file
plugins:
- "@prettier/plugin-oxc"
Due to package size limitations, this plugin is not included in the prettier package, it needs to be installed separately.
For more information, check the package homepage.
Many thanks to the OXC team(@boshen, @overlookmotel, and other contributors).
@prettier/plugin-hermes (#17520 by @fisker) {#change-17520}@prettier/plugin-hermes is based on Hermes JS Engine.
This plugin includes a new parser hermes (Flow syntax), to use this plugin:
Install the plugin
yarn add --dev prettier @prettier/plugin-hermes
Add the following to your .prettierrc file
plugins:
- "@prettier/plugin-hermes"
Due to package size limitations, this plugin is not included in the prettier package, it needs to be installed separately.
We plan to make this as the default parser for Flow syntax support in v4, we'll also remove babel-flow parser in v4, please give it a try.
For more information, check the package homepage.
Many thanks to the Hermes team.
SequenceExpression in ReturnStatement and ExpressionStatement (#17085 by @TYKevin) {#change-17085}// Input
function a() {
return ( a, b)
}
(a(), b());
// Prettier 3.5
function a() {
return a, b;
}
a(), b();
// Prettier 3.6
function a() {
return (a, b);
}
(a(), b());
AssignmentExpression in class property keys (#17145 by @fisker) {#change-17145}Previously we only add parentheses to AssignmentExpression in object keys, but not in class property keys. Thanks to Biome for bringing our attention to this inconsistency.
// Input
a = {
[(x = "key")]: 1,
}
class A {
[(x = "property")] = 1;
[(x = "method")]() {}
}
// Prettier 3.5
a = {
[(x = "key")]: 1,
};
class A {
[x = "property"] = 1;
[(x = "method")]() {}
}
// Prettier 3.6
a = {
[(x = "key")]: 1,
};
class A {
[(x = "property")] = 1;
[(x = "method")]() {}
}
There is an inconsistency when formatting member expression where the object is a number before Prettier 3.6.
When using babel parser(and other Babel based parsers), we print the number as unparenthesized, when using typescript parser(and other ESTree parsers), we print it as parenthesized.
Technically parentheses are not needed, but if we print it as 1?.toString() and later users realize it's unnecessary to use ?., users can't simply remove the question mark because 1.toString() will raise a SyntaxError, for this reason, we decide to always put parentheses around it.
// Input
(1)?.toString();
(1.5)?.toString();
// Prettier 3.5 (--parser=babel)
1?.toString();
1.5?.toString();
// Prettier 3.5 (--parser=typescript)
(1)?.toString();
(1.5)?.toString();
// Prettier 3.6
(1)?.toString();
(1.5)?.toString();
Records & Tuples (#17363 by @fisker) {#change-17363}The ES proposal JavaScript Records & Tuples Proposal has been withdrawn.
// Input
const Heading = styled.h1`
font-size: var(--font-size-h${level});
`;
// Prettier 3.5
const Heading = styled.h1`
font-size: var(--font-size-h ${level});
`;
// Prettier 3.6
const Heading = styled.h1`
font-size: var(--font-size-h${level});
`;
// Input
didScheduleRenderPhaseUpdateDuringThisPassFoo = didScheduleRenderPhaseUpdate = true
// Prettier 3.5 (--parser=babel)
didScheduleRenderPhaseUpdateDuringThisPassFoo =
didScheduleRenderPhaseUpdate = true;
// Prettier 3.5 (--parser=typescript)
didScheduleRenderPhaseUpdateDuringThisPassFoo = didScheduleRenderPhaseUpdate =
true;
// Prettier 3.6
didScheduleRenderPhaseUpdateDuringThisPassFoo =
didScheduleRenderPhaseUpdate = true;
// Input
s.get(u)?.trigger({ triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123 });
// Prettier 3.5 (--parser=babel)
s.get(u)?.trigger({
triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123,
});
// Prettier 3.5 (--parser=typescript)
s
.get(u)
?.trigger({ triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123 });
// Prettier 3.6
s.get(u)?.trigger({
triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123,
});
// Input
const a = { [y?.z]() {} };
class A { [y?.z]() {} };
// Prettier 3.5
const a = { [y?.z]?() {} };
class A {
[y?.z]?() {}
}
// Prettier 3.6
const a = { [y?.z]() {} };
class A {
[y?.z]() {}
}
acorn and meriyah parser (#17491, #17566 by @ArnaudBarre, #17600 by #fisker) {#change-17491}This was previously only supported by the Babel parser.
<!-- prettier-ignore -->// Input
/** @type {MyType} */ (x).foo;
// Prettier 3.5 (--parser=acorn|meriyah)
/** @type {MyType} */ x.foo;
// Prettier 3.6
/** @type {MyType} */ (x).foo;
// Input
foo
// Comment
`x`
// Prettier 3.5 (First format)
foo// Comment
`x`;
// Prettier 3.5 (Second format)
foo // Comment
`x`;
// Prettier 3.6
foo // Comment
`x`;
// Input
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => (
<h2 key={i}>{i + 1}</h2>
))}
</div>
</SuspendyTree>;
// Prettier 3.5 (ESTree based parsers like espree and typescript)
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => <h2 key={i}>{i + 1}</h2>)}
</div>
</SuspendyTree>;
// Prettier 3.5 (babel and babel-ts parser)
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => (
<h2 key={i}>{i + 1}</h2>
))}
</div>
</SuspendyTree>;
// Prettier 3.6 (parsers of both types)
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => (
<h2 key={i}>{i + 1}</h2>
))}
</div>
</SuspendyTree>;
TSImportType (#16881 by @fisker) {#change-16881}// Input
type A = import("foo", {with: {type: "json"}})
// Prettier 3.5
type A = import("foo")
// Prettier 3.6
type A = import("foo", { with: { type: "json" } });
// Input
export type ErrorLike =
SerializedProps<Error> &
// cause is a new addition to Error that is not yet available in all runtimes. We have added
// it to try and pinpoint additional reasoning for failures such as Node's fetch.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };
// Prettier 3.5
export type ErrorLike =
SerializedProps<Error> & // cause is a new addition to Error that is not yet available in all runtimes. We have added
// it to try and pinpoint additional reasoning for failures such as Node's fetch.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };
// Prettier 3.5 (second format)
export type ErrorLike =
SerializedProps<Error> & // it to try and pinpoint additional reasoning for failures such as Node's fetch. // cause is a new addition to Error that is not yet available in all runtimes. We have added
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };
// Prettier 3.6
export type ErrorLike = SerializedProps<Error> &
// cause is a new addition to Error that is not yet available in all runtimes. We have added
// it to try and pinpoint additional reasoning for failures such as Node's fetch.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };
// Input
type A = { readonly
[A in B]: T}
// Prettier 3.5
type A = {
readonly [A in B]: T;
};
// Prettier 3.6
type A = { readonly [A in B]: T };
prettier-ignored index-signature (#17538 by @sosukesuzuki) {#change-17538}// Input
type foo = {
// prettier-ignore
[key: string]: bar;
};
// Prettier 3.5
type foo = {
// prettier-ignore
[key: string]: bar;;
};
// Prettier 3.6
type foo = {
// prettier-ignore
[key: string]: bar;
};
ConditionalTypeAnnotation (#17196 by @fisker) {#change-17196}// Input
type T<U> = 'a' | ('b' extends U ? 'c' : empty);
type T<U> = 'a' & ('b' extends U ? 'c' : empty);
// Prettier 3.5
type T<U> = "a" | "b" extends U ? "c" : empty;
type T<U> = "a" & "b" extends U ? "c" : empty;
// Prettier 3.6
type T<U> = "a" | ("b" extends U ? "c" : empty);
type T<U> = "a" & ("b" extends U ? "c" : empty);
// Input
// Comment
// Prettier 3.5
SyntaxError: Unexpected token (1:11)
> 1 | // Comment
| ^
// Prettier 3.6
// Comment
// Input
[1, (2)]
// Prettier 3.5
[1, 2]
// Prettier 3.6
SyntaxError: 'ParenthesizedExpression' is not allowed in JSON. (1:5)
> 1 | [1, (2)]
| ^^^
@utility directive for Tailwind (#17362 by @sosukesuzuki) {#change-17362}This change supports @utility directive for Tailwind CSS V4.
/* Input */
@utility tab-* {
tab-size: --value(--tab-size-*);
}
/* Prettier 3.5 */
@utility tab-* {
tab-size: --value(--tab-size- *);
}
/* Prettier 3.6 */
@utility tab-* {
tab-size: --value(--tab-size-*);
}
:has pseudo call (#17541 by @sosukesuzuki) {#change-17541}/* Input */
li:has(
path[d="M544,272H480V150.627L523.314,107.314A16,16,0,0,0,500.686,84.687L457.373,128H415a127.00381,127.00381,0,1,0-254,0H118.627L75.314,84.687A16,16,0,1,0,52.686,107.314L96,150.627V272H32a16,16,0,0,0,0,32H96v24a174.98856,174.98856,0,0,0,30.484,98.889L68.687,484.686a15.99972,15.99972,0,1,0,22.627,22.627l55.616-55.616A175.45165,175.45165,0,0,0,272,504h32a175.45165,175.45165,0,0,0,125.07-52.303l55.616,55.616a15.99972,15.99972,0,0,0,22.627-22.627l-57.797-57.797A174.98856,174.98856,0,0,0,480,328V304h64a16,16,0,0,0,0-32ZM288,32.01263A95.99568,95.99568,0,0,1,383,128H193A95.99568,95.99568,0,0,1,288,32.01263ZM448,328c0,79.401-64.598,144-144,144V236a12.00052,12.00052,0,0,0-12-12h-8a12.00052,12.00052,0,0,0-12,12V472c-79.402,0-144-64.599-144-144V160H448Z"]
) {
display: none;
}
/* Prettier 3.5 */
li:has(
path[d="M544,272H480V150.627L523.314,107.314A16,16,0,0,0,500.686,84.687L457.373,128H415a127.00381,127.00381,0,1,0-254,0H118.627L75.314,84.687A16,16,0,1,0,52.686,107.314L96,150.627V272H32a16,16,0,0,0,0,32H96v24a174.98856,174.98856,0,0,0,30.484,98.889L68.687,484.686a15.99972,15.99972,0,1,0,22.627,22.627l55.616-55.616A175.45165,175.45165,0,0,0,272,504h32a175.45165,175.45165,0,0,0,125.07-52.303l55.616,55.616a15.99972,15.99972,0,0,0,22.627-22.627l-57.797-57.797A174.98856,174.98856,0,0,0,480,328V304h64a16,16,0,0,0,0-32ZM288,32.01263A95.99568,95.99568,0,0,1,383,128H193A95.99568,95.99568,0,0,1,288,32.01263ZM448,328c0,79.401-64.598,144-144,144V236a12.00052,12.00052,0,0,0-12-12h-8a12.00052,12.00052,0,0,0-12,12V472c-79.402,0-144-64.599-144-144V160H448Z"]
) {
display: none;
}
/* Prettier 3.6 */
li:has(
path[d="M544,272H480V150.627L523.314,107.314A16,16,0,0,0,500.686,84.687L457.373,128H415a127.00381,127.00381,0,1,0-254,0H118.627L75.314,84.687A16,16,0,1,0,52.686,107.314L96,150.627V272H32a16,16,0,0,0,0,32H96v24a174.98856,174.98856,0,0,0,30.484,98.889L68.687,484.686a15.99972,15.99972,0,1,0,22.627,22.627l55.616-55.616A175.45165,175.45165,0,0,0,272,504h32a175.45165,175.45165,0,0,0,125.07-52.303l55.616,55.616a15.99972,15.99972,0,0,0,22.627-22.627l-57.797-57.797A174.98856,174.98856,0,0,0,480,328V304h64a16,16,0,0,0,0-32ZM288,32.01263A95.99568,95.99568,0,0,1,383,128H193A95.99568,95.99568,0,0,1,288,32.01263ZM448,328c0,79.401-64.598,144-144,144V236a12.00052,12.00052,0,0,0-12-12h-8a12.00052,12.00052,0,0,0-12,12V472c-79.402,0-144-64.599-144-144V160H448Z"]
) {
display: none;
}
// Input
.what {
.make-modifier(1A, "1a.png");
.make-modifier(AA, "1a.png");
}
// Prettier 3.5
.what {
.make-modifier(1a, "1a.png");
.make-modifier(AA, "1a.png");
}
// Prettier 3.6
.what {
.make-modifier(1A, "1a.png");
.make-modifier(AA, "1a.png");
}
<!-- Input -->
<constructor>
text
</constructor>
<!-- Prettier 3.5 -->
TypeError: Vn(...).startsWith is not a function
<!-- Prettier 3.6 -->
<constructor> text </constructor>
TemplateLiteral introduced in Angular 19.2 (#17238 by @fisker) {#change-17238}Angular 19.2 added support for TemplateLiteral.
<!-- Input -->
<div>{{ `Hello, ${
getName('world')}` }}</div>
<!-- Prettier 3.5 -->
<div>
{{ `Hello, ${
getName('world')}` }}
</div>
<!-- Prettier 3.6 -->
<div>{{ `Hello, ${getName("world")}` }}</div>
track in angular @for control-flow (#17280 by @claudio-herger) {#change-17280}// Input
@for (item of items; let i = $index; let count = $count; track block) {}
// Prettier 3.5
@for (item of items; let i = $index; let count = $count; track: block) {}
// Prettier 3.6
@for (item of items; let i = $index; let count = $count; track block) {}
// Input
{{
( (a in (b)))
}}
{{
( (tag ` a ${ b } \u0063 `))
}}
{{
( (` a ${ b } \u0063 `))
}}
{{ void(1 + 2) }}
// Prettier 3.5
The new syntax is not correctly recognized.
// Prettier 3.6
{{ a in b }}
{{ tag` a ${b} \u0063 ` }}
{{ ` a ${b} \u0063 ` }}
{{ void (1 + 2) }}
<mj-style> tag (#17338 by @iryusa) {#change-17338}<!-- Input -->
<mj-style>
.hello {
color: blue;
border: 1px solid blue;
font-size:12px;
} p { font-size: 14px; }
</mj-style>
<!-- Prettier 3.5 -->
<mj-style>
.hello { color: blue; border: 1px solid blue; font-size:12px; } p { font-size:
14px; }
</mj-style>
<!-- Prettier 3.6 -->
<mj-style>
.hello {
color: blue;
border: 1px solid blue;
font-size: 12px;
}
p {
font-size: 14px;
}
</mj-style>
<mj-style> and <mj-raw> (#17400 by @fisker) {#change-17400}<!-- Input -->
<mj-style>
a::before {
content: "</p>";
}
</mj-style>
<!-- Prettier 3.5 -->
SyntaxError: Unexpected closing tag "p".
<!-- Prettier 3.6 -->
Correctly parsed as CSS.
<!-- Input -->
> `x`
> `y`
> _x_
> _y_
> [foo](http://foo)
> [bar](http://bar)
> `this` behaves
> `correctly`
<!-- Prettier 3.5 -->
> `x` > `y`
> _x_ > _y_
> [foo](http://foo) > [bar](http://bar)
> `this` behaves `correctly`
<!-- Prettier 3.6 -->
> `x` `y`
> _x_ _y_
> [foo](http://foo) [bar](http://bar)
> `this` behaves `correctly`
<!-- Input -->
- Level 1
- Level 1-1
- Level 2
<!-- Prettier 3.5 -->
- Level 1
- Level 1-1
- Level 2
<!-- Prettier 3.6 -->
- Level 1
- Level 1-1
- Level 2
Most markdown implementations don't support 1**_2_**3 so prefer 1***2***3.
<!-- Input -->
1***2***3
1**_2_**3
<!-- Prettier 3.5 -->
1**_2_**3
1**_2_**3
<!-- Prettier 3.6 -->
1***2***3
1***2***3
# Input
---
myDict: {}
# comment
myList: []
# comment
# Prettier 3.5
---
myDict:
{}
# comment
myList:
[]
# comment
# Prettier 3.6
---
myDict: {}
# comment
myList: []
# comment
URL in plugins option (#17166 by @fisker) {#change-17166}plugins option now accepts URL with file: protocol or a url string that starts with file: in all public APIs.
// `URL`
await prettier.check("foo", {
parser: "my-cool-parser",
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.format("foo", {
parser: "my-cool-parser",
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.formatWithCursor("foo", {
parser: "my-cool-parser",
cursorOffset: 2,
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.getFileInfo("/path/to/file", {
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.getSupportInfo({
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
// URL string
await prettier.check("foo", {
parser: "my-cool-parser",
plugins: ["file:///path/to/plugin.js"],
});
await prettier.format("foo", {
parser: "my-cool-parser",
plugins: ["file:///path/to/plugin.js"],
});
await prettier.formatWithCursor("foo", {
parser: "my-cool-parser",
cursorOffset: 2,
plugins: ["file:///path/to/plugin.js"],
});
await prettier.getFileInfo("/path/to/file", {
plugins: ["file:///path/to/plugin.js"],
});
await prettier.getSupportInfo({
plugins: ["file:///path/to/plugin.js"],
});
URL as custom config file in resolveConfig (#17167 by @fisker) {#change-17167}prettier.resolveConfig() now accepts an URL with file: protocol or a url string that starts with file: as custom config file location.
// `URL`
await prettier.resolveConfig("path/to/file", {
config: new URL("/path/to/prettier-config-file", import.meta.url),
});
// URL string
await prettier.resolveConfig("path/to/file", {
config: "file:///path/to/prettier-config-file",
});
*.frag files as JavaScript files (#17178 by @fisker) {#change-17178}*.frag was interpreted as JavaScript files, but .frag is also used in GLSL(OpenGL Shading Language). It causes error when Prettier try to format them as JavaScript files.
Since Prettier 3.6, *.frag files except *.start.frag, *.end.frag, start.frag, and end.frag are no longer treated as JavaScript files.
If you have JavaScript files with .frag that do not match the patterns mentioned above, you can config with overrides.
export default {
overrides: {
files: "**/*.frag",
options: {
parser: "babel",
},
},
};
isSupported function support for languages API (#17331 by @JounQin, #17490 by @fisker) {#change-17331}Previously, languages API for custom plugins only supported inferring parser based on the file basename or extension.
Prettier 3.6 added isSupported: (options: { filepath: string }) => boolean function to allow plugin check if file is supported based on the full path (eg: files in a specific directory).
:::note
Prettier can not ensure that filepath exists on disk.
When using from APIs(eg: prettier.format()), Prettier can not ensure it's a valid path either.
:::
If no isSupported provided, it just behaves the same way as before.
export const languages = [
{
name: "foo",
parsers: ["foo"],
isSupported: ({ filepath }) => filepath.includes(".foo"),
},
];
mjml parser (#17339 by @fisker) {#change-17339}We already support MJML in previous version with html parser, in order to distinguish MJML-specific a new mjml parser added.
--check-ignore-pragma (#17344 by @wnayes) {#change-17344}Individual files can now opt out of formatting via @noformat or @noprettier "pragma" comments at the top of the file.
To enable this feature, use the new option --check-ignore-pragma (checkIgnorePragma via configuration or API).
Language plugins can implement support for this feature. Most built-in parsers, including JavaScript (TypeScript), CSS, HTML, JSON, Markdown (MDX), YAML, and GraphQL, were updated to support this feature.
<!-- prettier-ignore -->/**
* @noformat
*/
export default matrix(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
prettier.getFileInfo() (#17548 by @fisker) {#change-17548}In previous version, prettier.getFileInfo() only read parser config from .prettierrc, but doesn't load plugins to infer parser from plugin languages, Prettier 3.6 fixed it.
// prettier-plugin-foo
export const languages = [
{
parsers: ["foo"],
extensions: [".foo"],
},
];
# .prettierrc
plugins:
- prettier-plugin-foo
prettier --file-info file.foo
# Prettier 3.5
{ "ignored": false, "inferredParser": null }
# Prettier 3.6
{ "ignored": false, "inferredParser": "foo" }
Previously when inferring parser for file, builtin plugins are checked first, so plugins are not able to override parsers for files like .js.
// prettier-plugin-foo
export const languages = [
{
parsers: ["foo"],
extensions: [".js"],
},
];
// prettier.config.js
import * as prettierPluginFoo from "prettier-plugin-foo";
export default {
plugins: [prettierPluginFoo],
};
prettier --file-info file.js
# Prettier 3.5
{ "ignored": false, "inferredParser": "babel" }
# Prettier 3.6
{ "ignored": false, "inferredParser": "foo" }
--config and --no-config together (#12221 by @Balastrong) {#change-12221}$ prettier --config=.prettierrc --no-config .
[error] Cannot use --no-config and --config together.
--cache-strategy=content (#17438 by @fisker) {#change-17438}In previous version, when using --cache-strategy=content, if the file modified time changed, it still gets re-formatted even the file content didn't change, Prettier 3.6 fixed it.
touch unknown
prettier --check unknown
# Prettier 3.5
Checking formatting...
unknown
[error] No parser could be inferred for file "</path/to/unknown>".
All matched files use Prettier code style!
# Prettier 3.6
Checking formatting...
unknown
[error] No parser could be inferred for file "</path/to/unknown>".
Error occurred when checking code style in the above file.
touch unknown
prettier --check unknown > /dev/null;echo $?
# Prettier 3.5
[error] No parser could be inferred for file "</path/to/unknown>".
0
# Prettier 3.6
[error] No parser could be inferred for file "</path/to/unknown>".
2
cursorOffset (#17254 by @fisker) {#change-17254}<!-- Input (--cursor-offset=1) -->
# Angular note
```typescript
import {Component} from '@angular/core';
@Component({
selector: 'app-root',
standalone: true,
imports: [],
template: `
<h1>
{{ title }}</h1>
`,
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'default';
}
```
<!-- Prettier 3.5 -->
Error: There are too many 'cursor' in doc.
<!-- Prettier 3.6 -->
# Angular note
```typescript
import { Component } from "@angular/core";
@Component({
selector: "app-root",
standalone: true,
imports: [],
template: `
<h1>
{{ title }}
</h1>
`,
styleUrls: ["./app.component.css"],
})
export class AppComponent {
title = "default";
}
```