Saltar al contenido principal

Prettier 3.2: Compatibilidad con JSONC y expresiones ICU de Angular

· 7 min de lectura
Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Esta versión incluye nuevas características como la adición de un analizador JSONC, soporte para expresiones ICU de Angular y numerosas correcciones de errores.

Seguimos solicitando retroalimentación sobre la opción --experimental-ternaries lanzada en Prettier 3.1. Por favor, lee A curious case of the ternaries y responde mediante el enlace de Google Forms proporcionado.

Además, recomendamos leer Prettier's CLI: A Performance Deep Dive de Fabio Spampinato. Esta CLI más rápida está programada para lanzarse como versión 4.0.

Si aprecias Prettier y deseas apoyar nuestro trabajo, considera patrocinarnos directamente a través de nuestro OpenCollective o patrocinando los proyectos de los que dependemos, como typescript-eslint, remark y Babel. ¡Gracias por tu continuo apoyo!

Destacados

JSON

Nuevo analizador jsonc añadido (#15831 por @fisker)

Anteriormente, inferíamos que el analizador de archivos .jsonc era json, pero si queríamos mantener la coma final, debíamos usar una configuración alternativa poco elegante: {parser: "json5", quoteProps: "preserve", singleQuote: false}.

El nuevo analizador jsonc:

  • Siempre entrecomilla las claves de los objetos.

  • Encierra las cadenas con comillas dobles.

  • Por supuesto, respeta la opción trailingComma.

Angular

Soporte para formateo de expresiones ICU de Angular (#15777 por @sosukesuzuki)

Admite dos tipos de expresiones ICU de Angular: plural y select.

<span i18n>
Updated:
{minutes, plural,
=0 {just now}
=1 {one minute ago}
other {{{minutes}} minutes ago}
}
</span>

<span i18n>
The author is {gender, select, male {male} female {female} other {other}}
</span>

Otros cambios

JavaScript

Evitar introducción de saltos de línea en interpolaciones de plantillas (#15209 por @bakkot)

En una cadena de plantilla como

`this is a long message which contains an interpolation: ${format(data)} <- like this`;

evita añadir saltos de línea al formatear la expresión a menos que ya existan o sean inevitables (por ejemplo, en funciones anidadas). Anteriormente se introducían saltos cuando alguna interpolación era lo suficientemente "no simple":

`this is a long message which contains an interpolation: ${format(
data,
)} <- like this`;

Ahora se mantendrá sin modificar.

Si ya existe un salto de línea dentro de ${...}, se formatea normalmente.

Corregir formato no idempotente en cadenas de métodos con líneas vacías (#15522 por @seiyab)

// Input
Foo.a()

.b();

// Prettier 3.1 (first format)
Foo.a()
.b();

// Prettier 3.1 (second format)
Foo.a().b();


// Prettier 3.2
Foo.a()

.b();

Corregir formato de operadores ternarios en llamadas de función (#15677 por @fisker)

// Input
stopDirectory = await (useCache
? memoizedFindProjectRoot
: findProjectRootWithoutCache)(path.dirname(path.resolve(filePath)));

// Prettier 3.1
stopDirectory = await (useCache
? memoizedFindProjectRoot
: findProjectRootWithoutCache)(path.dirname(path.resolve(filePath)));

// Prettier 3.2
stopDirectory = await (
useCache ? memoizedFindProjectRoot : findProjectRootWithoutCache
)(path.dirname(path.resolve(filePath)));

Soluciona inconsistencias para el encadenamiento opcional (#15806 por @fisker)

Solo ocurre al usar los parsers typescript, meriyah u otros parsers ESTree excepto babel.

// Input
function someFunctionName() {
return isEqual(a.map(([t, _]) => t?.id), b.map(([t, _]) => t?.id));
return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id));
}
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere?.includes(listingId),
);

// Prettier 3.1
function someFunctionName() {
return isEqual(
a.map(([t, _]) => t?.id),
b.map(([t, _]) => t?.id),
);
return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id));
}
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere?.includes(listingId),
);

// Prettier 3.2
function someFunctionName() {
return isEqual(
a.map(([t, _]) => t?.id),
b.map(([t, _]) => t?.id),
);
return isEqual(
a?.map(([t, _]) => t?.id),
b?.map(([t, _]) => t?.id),
);
}
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere?.includes(listingId),
);

Soluciona problemas con comentarios en if (#15826 por @fisker)

// Input
if (foo) for (i = 2; i > 0; i--) console.log(i); // comment 1
else bar();

for (;;){
if (foo) continue; // comment 2
else bar();
}

// Prettier 3.1
Error: Comment "comment 2" was not printed. Please report this error!

// Prettier 3.2
if (foo)
for (i = 2; i > 0; i--) console.log(i); // comment 1
else bar();

for (;;) {
if (foo)
continue; // comment 2
else bar();
}

TypeScript

Mejora el diseño de alias para tipos condicionales (#15811 por @seiyab)

// Input
type FallbackFlags<F extends Flags | undefined> =
Equals<NonNullableFlag<F>["flags"], {}> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

// Prettier 3.1
type FallbackFlags<F extends Flags | undefined> = Equals<
NonNullableFlag<F>["flags"],
{}
> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

// Prettier 3.2
type FallbackFlags<F extends Flags | undefined> =
Equals<NonNullableFlag<F>["flags"], {}> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

HTML

Soluciona el formato de elementos no cerrados ignorados con prettier-ignore (#15748 por @fisker)

<!-- Input -->
<!-- prettier-ignore -->
<h1>
Hello <span>world!

<!-- Prettier 3.1 -->
<!-- prettier-ignore -->
<h1>

<!-- Prettier 3.2 -->
<!-- prettier-ignore -->
<h1>
Hello <span>world!

Angular

Soluciona bloques de control de Angular ignorados con prettier-ignore (#15827 por @fisker)

<!-- Input -->
<!-- prettier-ignore -->
@if (condition) {
Foo
} @else {
Other
}

<!-- Prettier 3.1 -->
<!-- prettier-ignore -->
@if (condition) {
Foo
}
} @else {
Other
}

<!-- Prettier 3.2 -->
<!-- prettier-ignore -->
@if (condition) {
Foo
}
@else {
Other
}

Evita agregar dos puntos para track en la tercera expresión de bloques for (#15887 por @sosukesuzuki)

<!-- Input -->
@for (item of items; let i = $index; track block) {}

<!-- Prettier 3.1 -->
@for (item of items; let i = $index; track: block) {}

<!-- Prettier 3.2 -->
@for (item of items; let i = $index; track block) {}

Ember / Handlebars

Preserva segmentos literales en rutas (#15605 por @maxpowa)

Soluciona casos donde archivos Handlebars que contenían segmentos literales se reformateaban eliminando estos segmentos, causando errores de sintaxis.

<!-- Input -->
{{input.[funky<api!response]}}
{{input.[this one has spaces]}}
{{input.[anotherone].[0]}}

<!-- Prettier 3.1 -->
{{input.funky<api!response}}
{{input.this one has spaces}}
{{input.anotherone.0}}

<!-- Prettier 3.2 -->
{{input.[funky<api!response]}}
{{input.[this one has spaces]}}
{{input.anotherone.[0]}}

GraphQL

Mejora el formato de tipos union en GraphQL (#15870 por @ArchitGajjar)

# Input
union SearchResult = Conference| Festival | Concert | Venue | Conference| Festival | Concert | Venue

# Prettier 3.1
union SearchResult =
Conference
| Festival
| Concert
| Venue
| Conference
| Festival
| Concert
| Venue

# Prettier 3.2
union SearchResult =
| Conference
| Festival
| Concert
| Venue
| Conference
| Festival
| Concert
| Venue

API

Soporta rutas absolutas como plugins en archivos de configuración (#15666 por @fisker)

// prettier.config.cjs
module.exports = {
plugins: [
// posix style
"/path/to/plugin.js",
// Windows style
"D:\\\\path\\to\\plugin.js",
// Use `require.resolve`
require.resolve("my-awesome-prettier-plugin"),
],
};

Soluciona definiciones de tipos para getFileInfo y getSupportInfo (#15854 por @auvred)

const plugin: Plugin = {};

prettier.getFileInfo("./file.ext", {
plugins: [plugin],
});

prettier.getSupportInfo({ plugins: [plugin], showDeprecated: true });

Varios

Corrige afirmación incorrecta en documentación sobre incompatibilidad de cursorOffset con rangeStart/rangeEnd (#15750 por @ExplodingCabbage)

La opción cursorOffset ha sido compatible con rangeStart/rangeEnd durante más de 5 años gracias al trabajo de @ds300. Sin embargo, la documentación de Prettier (incluyendo el texto CLI --help) seguía afirmando lo contrario erróneamente. La documentación ahora está corregida.