Hoppa till huvudinnehållet

Prettier 3.1: Ny experimentell ternärformatering och Angular control flow-syntax!

· 12 min att läsa
Inofficiell Beta-översättning

Denna sida har översatts av PageTurner AI (beta). Inte officiellt godkänd av projektet. Hittade du ett fel? Rapportera problem →

Den här versionen återinför indrag för kapslade ternärer tillsammans med en ny flagga --experimental-ternaries för att prova ett nyare "curious ternary"-format som fungerar bättre för djupt kapslade villkorsuttryck. Vi är väldigt intresserade av er feedback på det experimentella formatet innan det blir standardbeteende senare i år!

Vi har också lagt till stöd för control flow-syntaxen i Angular v17. För detaljer om syntaxen, läs det officiella Angular-inlägget.

Om du uppskattar Prettier och vill stödja vårt arbete, överväg att sponsra oss direkt via vår OpenCollective eller genom att sponsra de projekt vi förlitar oss på, såsom typescript-eslint, remark och Babel. Tack för ert fortsatta stöd!

Höjdpunkter

JavaScript

Återinför indrag för kapslade ternärer (#9559 by @rattrayalex)

// Input
const message =
i % 3 === 0 && i % 5 === 0
? "fizzbuzz"
: i % 3 === 0
? "fizz"
: i % 5 === 0
? "buzz"
: String(i);


// Prettier 3.0
const message =
i % 3 === 0 && i % 5 === 0
? "fizzbuzz"
: i % 3 === 0
? "fizz"
: i % 5 === 0
? "buzz"
: String(i);

// Prettier 3.1
const message =
i % 3 === 0 && i % 5 === 0
? "fizzbuzz"
: i % 3 === 0
? "fizz"
: i % 5 === 0
? "buzz"
: String(i);

Ny Experimentell Ternärformatering: En Sällsam Historia om Ternärer (#13183 by @rattrayalex)

Detta implementeras bakom en --experimental-ternaries-flagga.

Vi flyttar ? i flerradiga ternärer till slutet av första raden istället för början av andra raden, tillsammans med flera relaterade ändringar.

Även om det kan verka konstigt först, visar betatestning att utvecklare efter några timmars användning tycker att det gör kapslade ternärer mycket mer lättlästa och användbara.

Denna PR löser ett av våra högt uppröstade ärenden utan problemen som dess föreslagna lösning skulle återinföra.

Se A curious case of the ternaries för mer information.

Exempel
// "Questioning" ternaries for simple ternaries:
const content =
children && !isEmptyChildren(children) ?
render(children)
: renderDefaultChildren();

// "Case-style" ternaries for chained ternaries:
const message =
i % 3 === 0 && i % 5 === 0 ? "fizzbuzz"
: i % 3 === 0 ? "fizz"
: i % 5 === 0 ? "buzz"
: String(i);

// Smoothly transitions between "case-style" and "questioning" when things get complicated:
const reactRouterResult =
children && !isEmptyChildren(children) ? children
: props.match ?
component ? React.createElement(component, props)
: render ? render(props)
: null
: null

Stöd för nya syntaxer i Babel 7.23.0 (#15485, #15486, #15487, #15488 av @sosukesuzuki)

Vi stöder ny JS-syntax från Babel 7.23.0!

Source Phase Imports

Se https://github.com/tc39/proposal-source-phase-imports för mer information.

import source x from "mod";
Deferred Import Evaluation

Se https://github.com/tc39/proposal-defer-import-eval för mer information.

import defer * as ns from "mod";
Optional Chaining Assignments

Se https://github.com/tc39/proposal-optional-chaining-assignment för mer information.

maybeObj?.prop1 = value;

Angular

Stöd för Angular control flow (#15606 av @DingWeizhe, @fisker)

Lagt till stöd för inbyggd control flow i Angular 17. Rapportera gärna buggar om ni hittar några.

För mer information om control flow, se artikeln på den officiella bloggen.

https://blog.angular.io/introducing-angular-v17-4d7033312e4b

Andra ändringar

JavaScript

Fixa kommentarer mellan parenteser och funktionskropp (#15326 av @fisker)

// Input
function function_declaration()
// this is a function
{
return 42
}

(function function_expression()
// this is a function
{
return 42
})();

// Prettier 3.0
function function_declaration() {
// this is a function
return 42;
}

(function function_expression() // this is a function
{
return 42;
})();

// Prettier 3.1
function function_declaration() {
// this is a function
return 42;
}

(function function_expression() {
// this is a function
return 42;
})();
// Input
function function_declaration()
// this is a function
{
return 42
}

export default function()
// this is a function
{
return 42
}

// Prettier 3.0
TypeError: Cannot read properties of null (reading 'range')

// Prettier 3.1
function function_declaration() {
// this is a function
return 42;
}

export default function () {
// this is a function
return 42;
}

Tydliggör unära uttryck på vänstra sidan av instanceof och in (#15468 av @lucacasonato)

Parenteser läggs nu till runt unära uttryck på vänstra sidan av instanceof- och in-uttryck för att skilja på det unära uttrycket på vänster sida från ett unärt uttryck som appliceras på hela det binära uttrycket.

Detta hjälper till att fånga ett vanligt misstag där användaren avser att skriva !("x" in y) men istället skriver !"x" in y, vilket tolkas som det meningslösa uttrycket (!"x") in y.

// Input
!"x" in y;
!("x" in y);

// Prettier 3.0
!"x" in y;
!("x" in y);

// Prettier 3.1
(!"x") in y;
!("x" in y);

Rättar namnskiftning hos selektorer i styled components-interpolation (#15472 av @lucasols)

// Input
const StyledComponent = styled.div`
margin-right: -4px;

${Container}.isExpanded & {
transform: rotate(-180deg);
}
`;

const StyledComponent2 = styled.div`
margin-right: -4px;

${abc}.camelCase + ${def}.camelCase & {
transform: rotate(-180deg);
}
`;

// Prettier 3.0
const StyledComponent = styled.div`
margin-right: -4px;

${Container}.isexpanded & {
transform: rotate(-180deg);
}
`;

const StyledComponent2 = styled.div`
margin-right: -4px;

${abc}.camelcase + ${def}.camelCase & {
transform: rotate(-180deg);
}
`;

// Prettier 3.1 -- same as input

Formatera strängar med escape-sekvenser konsekvent (#15525 av @sosukesuzuki)

// Input
export const MSG_GENERIC_OPERATION_FAILURE_BODY_1 =
goog.getMsg("That's all we know");

export const MSG_GENERIC_OPERATION_FAILURE_BODY_2 =
goog.getMsg("That\'s all we know");

// Prettier 3.0
export const MSG_GENERIC_OPERATION_FAILURE_BODY_1 =
goog.getMsg("That's all we know");

export const MSG_GENERIC_OPERATION_FAILURE_BODY_2 = goog.getMsg(
"That's all we know",
);

// Prettier 3.1
export const MSG_GENERIC_OPERATION_FAILURE_BODY_1 =
goog.getMsg("That's all we know");

export const MSG_GENERIC_OPERATION_FAILURE_BODY_2 =
goog.getMsg("That's all we know");

Förbättrad formatering när tilldelningens vänstra sida kan brytas (#15547 av @sosukesuzuki)

// Input
params["redirectTo"] =
`${window.location.pathname}${window.location.search}${window.location.hash}`;

// Prettier 3.0
params[
"redirectTo"
] = `${window.location.pathname}${window.location.search}${window.location.hash}`;

// Prettier 3.1
params["redirectTo"] =
`${window.location.pathname}${window.location.search}${window.location.hash}`;

TypeScript

Rättar instabil kommentar efter sista parameter-egenskap (#15324 av @fisker)

// Input
class Class {
constructor(
private readonly paramProp: Type,
// comment
) {
}
}

// Prettier 3.0
class Class {
constructor(private readonly paramProp: Type) // comment
{}
}

// Prettier 3.0 (Second format)
class Class {
constructor(
private readonly paramProp: Type, // comment
) {}
}

// Prettier 3.1
class Class {
constructor(
private readonly paramProp: Type,
// comment
) {}
}

Stöd för inbäddad formatering i malliteraler annoterade med as const (#15408 av @sosukesuzuki)

// Input
const GQL_QUERY_WITH_CONST = /* GraphQL */ `
query S { shop }
` as const;

// Prettier 3.0
const GQL_QUERY_WITH_CONST = /* GraphQL */ `
query S { shop }
` as const;

// Prettier 3.1
const GQL_QUERY_WITH_CONST = /* GraphQL */ `
query S {
shop
}
` as const;

Rättar utskrift av kommentarer för sista operand i unionstyper (#15409 av @sosukesuzuki)

// Input
type Foo1 = (
| "thing1" // Comment1
| "thing2" // Comment2
)[]; // Final comment1
type Foo2 = (
| "thing1" // Comment1
| "thing2" // Comment2
) & Bar; // Final comment2

// Prettier 3.0
type Foo1 = (
| "thing1" // Comment1
| "thing2"
)[]; // Comment2 // Final comment1
type Foo2 = (
| "thing1" // Comment1
| "thing2"
) & // Comment2
Bar; // Final comment2

// Prettier 3.1
type Foo1 = (
| "thing1" // Comment1
| "thing2" // Comment2
)[]; // Final comment1
type Foo2 = (
| "thing1" // Comment1
| "thing2" // Comment2
) &
Bar; // Final comment2

Behåll nödvändiga parenteser runt specifika nyckelord/liknande identifierare i uttryckssatser för satisfies/as-uttryck (#15514 av @seiyab)

// Input
(type) satisfies never;


// Prettier 3.0
type satisfies never;


// Prettier 3.1
(type) satisfies never;

Flow

Stöd för as- och satisfies-uttryck i Flow (#15130 av @gkz)

// Input
const x = y as T;

// Prettier 3.0
// <error: unsupported>

// Prettier 3.1
const x = y as T;

Stöd för typargument på JSX-öppningselement i Flow (#15429 av @SamChou19815)

// Input
<Foo<bar> />;

// Prettier 3.0
<Foo />;

// Prettier 3.1
<Foo<bar> />;

Stöd för typargument efter typeof (#15466 av @sosukesuzuki)

Stödjer typargument efter typeof-syntax som introducerades i Flow v0.127.0:

type Foo = typeof MyGenericClass<string, number>;

SCSS

Dela inte upp anrop av SCSS-funktion med inledande bindestreck (#15370 av @auvred)

/* Input */
div {
width: -double(-double(3));
}

/* Prettier 3.0 */
div {
width: -double(- double(3));
}

/* Prettier 3.1 */
div {
width: -double(-double(3));
}

HTML

Rättar formatering av menu- och marquee-element (#15334 av @fisker)

<!-- Input -->
<menu><li><button onclick="copy()">Copy</button></li>
<li><button onclick="cut()">Cut</button></li>
<li><button onclick="paste()">Paste</button></li></menu>
<marquee
direction="down"
width="250"
height="200"
behavior="alternate"
style="border:solid"><marquee behavior="alternate"> This text will bounce </marquee></marquee>

<!-- Prettier 3.0 -->
<menu
><li><button onclick="copy()">Copy</button></li>
<li><button onclick="cut()">Cut</button></li>
<li><button onclick="paste()">Paste</button></li></menu
>
<marquee
direction="down"
width="250"
height="200"
behavior="alternate"
style="border: solid"
><marquee behavior="alternate"> This text will bounce </marquee></marquee
>

<!-- Prettier 3.1 -->
<menu>
<li><button onclick="copy()">Copy</button></li>
<li><button onclick="cut()">Cut</button></li>
<li><button onclick="paste()">Paste</button></li>
</menu>
<marquee
direction="down"
width="250"
height="200"
behavior="alternate"
style="border: solid"
>
<marquee behavior="alternate">This text will bounce</marquee>
</marquee>

Markdown

Kodar < och > i Markdown-URL:er (#15400 av @vivekjoshi556)

<!-- Input -->
[link](https://www.google.fr/()foo->bar)

<!-- Prettier 3.0 -->
[link](<https://www.google.fr/()foo->bar>)

<!-- Prettier 3.1 -->
[link](<https://www.google.fr/()foo-%3Ebar>)
<!-- Input -->
![link](<https://www.google.fr/()foo->bar>)

<!-- Prettier 3.0 -->
![link](<https://www.google.fr/()foo->bar>)

<!-- Prettier 3.1 -->
![link](<https://www.google.fr/()foo-%3Ebar>)

Dela inte rader mellan japansk kana och COMBINING KATAKANA-HIRAGANA (SEMI-)VOICED SOUND MARK (#15411 by @tats-u)

Denna PR åtgärdar #15410.

Japanska (semi-)tonade kana-tecken kan delas upp i två kodpunkter. Till exempel kan följande hiragana-tecken /ka/ representeras som:

が (U+304C) → か (U+304B) + ゙ (U+3099) → が (U+304C U+3099)

De flesta användare stöter inte på sådana uttryck förutom i filvägar på macOS. Det finns dock vissa tecken som endast kan representeras på detta sätt. Vissa japanska texter som måste skilja /ŋa̠/ (även om det inte är många japaner som använder det nuförtiden) från det vanliga /ga/ använder uttrycket "か゚" (U+304B U+309A).

nasalか゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚

Ovanstående Markdown formateras så här i Prettier 3.0:

nasalか゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け
゚こ゚

Det semi-tonade ljudmärket hamnar på nästa rad, vilket inte är korrekt. Med denna PR formateras nu käll-Markdown så här:

nasalか゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚
け゚こ゚

Det semi-tonade ljudmärket håller nu ihop med hiragana-tecknet "け".

API

Acceptera URL i prettier.{resolveConfig,resolveConfigFile,getFileInfo}() (#15332, #15354, #15360, #15364 by @fisker)

prettier.resolveConfig(), prettier.resolveConfigFile() och prettier.getFileInfo() accepterar nu en URL med file:-protokoll eller en URL-sträng som börjar med file://.

// `URL`
await prettier.resolveConfig(new URL("./path/to/file", import.meta.url));
await prettier.resolveConfigFile(new URL("./path/to/file", import.meta.url));
await prettier.getFileInfo(new URL("./path/to/file", import.meta.url));
await prettier.getFileInfo("/path/to/file", {
ignorePath: new URL("./.eslintignore", import.meta.url),
});

// URL string
await prettier.resolveConfig("file:///path/to/file");
await prettier.resolveConfigFile("file:///path/to/file");
await prettier.getFileInfo("file:///path/to/file");
await prettier.getFileInfo("/path/to/file", {
ignorePath: "file:///path/to/.eslintignore",
});

CLI

Bearbeta filer som endast stöds av tillägg (#15433 by @sosukesuzuki)

I Prettier 3.0, när en katalog angavs från CLI:n, bearbetades endast filer med standardstödda filändelser.

I följande scenario bör inte bara foo.js utan även foo.astro formateras:

# Prettier 3.0 version

$ ls .
foo.js foo.astro

$ cat .prettierrc
{ "plugins": ["prettier-plugin-astro"] }

$ prettier --write .
foo.js 20ms

Med denna uppdatering kommer nu både foo.js och foo.astro att formateras:

# Prettier 3.1 branch

$ prettier --write .
foo.js 20ms
foo.astro 32ms

Du kan ersätta prettier "**/*" --ignore-unknown med prettier . eftersom de nu är ekvivalenta.

Visa nyckelordet (unchanged) för tillgänglighet i CLI:n med --write (#15467 by @ADTC)

Tidigare var den enda skillnaden mellan en ändrad fil och en oförändrad fil den grå färgen på filnamnet. I exemplet nedan kan vi inte skilja på a.js och b.js eftersom färgen saknas. Detta problem är åtgärdat genom att lägga till nyckelordet (unchanged) vilket gör skillnaden tillgänglig utan färg.

prettier --write .

# Prettier 3.0
a.js 0ms
b.js 0ms
c.js 0ms (cached)

# Prettier 3.1
a.js 0ms
b.js 0ms (unchanged)
c.js 0ms (unchanged) (cached)

Åtgärda fel vid formatering av filnamn som innehåller specialtecken (#15597 by @fisker)

prettier "[with-square-brackets].js" --list

# Prettier 3.0
[error] Explicitly specified file was ignored due to negative glob patterns: "[with-square-brackets].js".

# Prettier 3.1
[with-square-brackets].js