Saltar al contenido principal

Prettier 3.4: Muchas correcciones de errores

· 20 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 numerosas correcciones de errores y otras mejoras.

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!

Otros cambios

JavaScript

Corregir impresión de literales de plantilla con arreglos (#13315 por @fisker, @syi0808)

// Input
const string = `${[[1, 2], [3, 4]]}`

// Prettier 3.3
const string = `${[
[2],
[4],
]}`;

// Prettier 3.4
const string = `${[
[1, 2],
[3, 4],
]}`;

Agregar paréntesis faltantes en literales de plantilla etiquetados (#16500 por @syi0808)

// Input
(String?.raw)``;
(getTag?.())``;

// Prettier 3.3
String?.raw``;
getTag?.()``;

// Prettier 3.4
(String?.raw)``;
(getTag?.())``;

No eliminar \ innecesarios en literales de cadena (#16563 por @sosukesuzuki, #16763 por @fisker)

Anteriormente, Prettier eliminaba caracteres de escape innecesarios (\) en literales de cadena. Sin embargo, este comportamiento era inconsistente ya que no se aplicaba a literales de plantilla, como se reportó en el issue #16542.

Esta incidencia es una solicitud para extender este comportamiento también a los literales de plantilla.

Tras discutirlo internamente, el equipo de Prettier concluyó que eliminar caracteres de escape innecesarios, ya sea en literales de cadena o de plantilla, es responsabilidad de un linter, no de un formateador.

Este cambio desactiva la eliminación de caracteres de escape innecesarios en literales de cadena en todos los lenguajes que soporta Prettier. Para mantener el comportamiento anterior, recomendamos usar reglas de ESLint como no-useless-escape.

Las comillas escapadas (ej. "\"\'") pueden dejar de escaparse al cambiar entre diferentes tipos de comillas. Esto se explica en la página Rationale de la documentación oficial.

// Input
const str = "\a";

// Prettier 3.3
const str = "a";

// Prettier 3.4
const str = "\a";

Mejorar formato de comentarios para expresiones lógicas en expresiones unarias (#16593 por @sosukesuzuki)

// Input
!(
cond1 || // foo
cond2 || // bar
cond3 // baz
);

// Prettier 3.3
!(
(
cond1 || // foo
cond2 || // bar
cond3
) // baz
);

// Prettier 3.4
!(
cond1 || // foo
cond2 || // bar
cond3 // baz
);

Eliminado soporte para sintaxis experimental (#16643, #16705 por @fisker)

TypeScript

Agregar paréntesis faltantes en literales de plantilla etiquetados (#16500 por @syi0808)

// Input
(String?.raw!)``;
(String?.raw)!``;

// Prettier 3.3
String?.raw!``;
String?.raw!``;

// Prettier 3.4
(String?.raw)!``;
(String?.raw)!``;

Conservar un comentario entre el decorador y la propiedad de parámetro modificada (#16574 por @sosukesuzuki)

La versión actual de Prettier mueve inesperadamente un comentario de línea entre una propiedad de parámetro modificada con readonly, private, public, etc. y un decorador. Esto genera código TypeScript inválido.

Este cambio garantiza que se conserva el formato original.

// Input
class Foo {
constructor(
@decorator
// comment
readonly foo,
) {}
}

// Prettier 3.3
class Foo {
constructor(
@decorator
readonly // comment
foo,
) {}
}

// Prettier 3.4
class Foo {
constructor(
@decorator
// comment
readonly foo,
) {}
}

Conservar un comentario entre el modificador y el nombre de la propiedad decorada (#16578 por @sosukesuzuki)

Existía un error donde los comentarios de bloque entre el modificador y el nombre de una propiedad decorada se trataban como comentarios finales del decorador. Este comportamiento era inesperado y carecía de idempotencia.

Con este cambio, se conserva la posición del comentario de bloque entre el modificador y el nombre de la propiedad.

// Input
class Foo {
@decorator
readonly /* comment */ propertyName;
}

// Prettier 3.3
class Foo {
@decorator /* comment */
readonly propertyName;
}

// Prettier 3.3 (second output)
class Foo {
@decorator /* comment */ readonly propertyName;
}

// Prettier 3.4
class Foo {
@decorator
readonly /* comment */ propertyName;
}

No imprimir un salto de línea adicional para funciones flecha con parámetros de tipo en asignaciones (#16586 por @sosukesuzuki)

Existía un error donde se insertaba una línea adicional al asignar una función fleva encadenada con parámetros de tipo a una variable si había un comentario de línea encima.

Este cambio garantiza que ya no se inserta la línea adicional.

// Input
const foo1 =
// comment
<T,>() => () => 1;

// Prettier 3.3
const foo1 =
// comment

<T,>() =>
() =>
1;

// Prettier 3.4
const foo1 =
// comment
<T,>() =>
() =>
1;

Admitir "Sentencias await de nivel superior" (#16729 por @fisker)

// Input
(await (await fetch()).json()).foo

// Prettier 3.3
await(await fetch()).json().foo;

// Prettier 3.4
(await (await fetch()).json()).foo;

Corregir saltos en herencia de clase aunque permanezca dentro del ancho de línea (#16730 por @fisker)

// Input
export class JiraCreatePixFraudDetectionGateway
implements Pick<IssuePixFraudDetectionGateway, "createPixFraudDetectionIssue">
{
constructor(private readonly logger: Logger) {
this.logger = logger.child({
context: JiraCreatePixFraudDetectionGateway.name,
});
}
}

// Prettier 3.3
export class JiraCreatePixFraudDetectionGateway
implements
Pick<IssuePixFraudDetectionGateway, "createPixFraudDetectionIssue">
{
constructor(private readonly logger: Logger) {
this.logger = logger.child({
context: JiraCreatePixFraudDetectionGateway.name,
});
}
}

// Prettier 3.4
export class JiraCreatePixFraudDetectionGateway
implements Pick<IssuePixFraudDetectionGateway, "createPixFraudDetectionIssue">
{
constructor(private readonly logger: Logger) {
this.logger = logger.child({
context: JiraCreatePixFraudDetectionGateway.name,
});
}
}

Imprimir declare antes de la accesibilidad en propiedades de clase (#16731 por @fisker)

// Input
class A {
declare private readonly name: string;
}

// Prettier 3.3
class A {
private declare readonly name: string;
}

// Prettier 3.4
class A {
declare private readonly name: string;
}

CSS

Resolver algunos tipos de desbordamiento en CSS (#16570 por @seiyab)

/* Input */
@media (prefers-reduced-data: no-preference) {
@font-face {
unicode-range: U+0000-00FF, U+0131,
U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
}

/* Prettier 3.3 */
@media (prefers-reduced-data: no-preference) {
@font-face {
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212,
U+2215, U+FEFF, U+FFFD;
}
}

/* Prettier 3.4 */
@media (prefers-reduced-data: no-preference) {
@font-face {
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
}
}

Eliminar sangría adicional en funciones de pseudo-clases (#16572 por @sosukesuzuki)

Este cambio corrige un error donde se añadía sangría adicional cuando se incluían saltos de línea en la lista de argumentos de funciones de pseudo-clases como :where(), :is() y :not.

/* Input */
:where(input:not([type="button"], [type="reset"], [type="submit"]), textarea, select) {
/* CSS here */
}

/* Prettier 3.3 */
:where(
input:not([type="button"], [type="reset"], [type="submit"]),
textarea,
select
) {
/* CSS here */
}

/* Prettier 3.4 */
:where(
input:not([type="button"], [type="reset"], [type="submit"]),
textarea,
select
) {
/* CSS here */
}

Corregir formato de comentarios de valor CSS incompletos (#16583 por @sosukesuzuki, @fisker)

Al formatear comentarios de valor CSS, la / final podría perderse, generando un comentario inválido.

Este cambio garantiza que los comentarios de valor no se trunquen.

/* Input */
h1 {
--OFF: /* OFF */;
}

/* Prettier 3.3 */
h1 {
--OFF: /* OFF *;
}

/* Prettier 3.4 */
h1 {
--OFF: /* OFF */;
}

SCSS

Corregir error al formatear archivos SCSS (#16607 por @fisker)

// Input
@if true {
$newKey: ($key: ( $theme-name: $value ))
}

// Prettier 3.3
Error

// Prettier 3.4
@if true {
$newKey: (
$key:
(
$theme-name: $value,
),
);
}

Corrección de posición incorrecta de coma final después de comentarios en SCSS (#16617 por @Ma-hawaj, @fisker)

/* Input */
$z-indexes: (
header: 1035,
overlay: 1202 // TODO: change to 1050 after bootstrap modals will be removed
);

/* Prettier 3.3 */
$z-indexes: (
header: 1035,
overlay: 1202 // TODO: change to 1050 after bootstrap modals will be removed,
);

/* Prettier 3.4 */
$z-indexes: (
header: 1035,
overlay: 1202, // TODO: change to 1050 after bootstrap modals will be removed
);

HTML

Mantener el doctype sin cambios en archivos no HTML (#16765 por @fisker)

En Prettier v3, convertimos a minúsculas el doctype de HTML5, lo cual es seguro para archivos HTML. Sin embargo, los usuarios pueden usar el parser html para formatear otros archivos como XHTML, donde convertir a minúsculas el doctype rompería los documentos XHTML.

A partir de Prettier 3.4, solo convertiremos a minúsculas el doctype de HTML5 (<!doctype html>) cuando la extensión del archivo sea .html o .htm. En otros casos, permanecerá sin cambios.

<!-- Input -->
<!-- foo.xhtml -->
<!DOCTYPE html>

<!-- Prettier 3.3 -->
<!doctype html>

<!-- Prettier 3.4 -->
<!DOCTYPE html>

Vue

Corrección de punto y coma extra insertado en enlaces de eventos Vue con caracteres no ASCII (#16733 por @fisker)

<!-- Input -->
<template>
<button @click="点击事件">点击!</button>
<button @click="onClick">Click!</button>
</template>

<!-- Prettier 3.3 -->
<template>
<button @click="点击事件;">点击!</button>
<button @click="onClick">Click!</button>
</template>

<!-- Prettier 3.4 -->
<template>
<button @click="点击事件">点击!</button>
<button @click="onClick">Click!</button>
</template>

Angular

Soporte para Angular 19 (#16862 por @fisker)

Angular 19 agregó soporte para la palabra clave typeof en expresiones de plantilla.

<!-- Input -->
<div>{{ typeof
x ===
'object' ? 'Y' : 'N'}}</div>

<!-- Prettier 3.3 -->
<div>
{{ typeof
x ===
'object' ? 'Y' : 'N'}}
</div>

// Prettier 3.4
<div>{{ typeof x === "object" ? "Y" : "N" }}</div>

Markdown

Eliminación de espacios excesivos después de prefijos de línea en listas desordenadas de Markdown (#15526 por @TomasLudvik)

<!-- Input -->
- first line
- second line indented
- third line
- fourth line
- fifth line

<!-- Prettier 3.3 -->
- first line
- second line indented
- third line
- fourth line
- fifth line

<!-- Prettier 3.4 -->
- first line
- second line indented
- third line
- fourth line
- fifth line

Corrección de ajuste incorrecto en oraciones con linkReference (#16546 por @seiyab)

<!-- Input (--prose-wrap=always) -->
This folder has [VHS] tape files to create gifs for the [Widget Showcase]. To run them, install VHS from main (the theme and screenshot commands are not yet released).

<!-- Prettier 3.3 -->
This folder has [VHS] tape files to create gifs for the [Widget Showcase]. To run
them, install VHS from main (the theme and screenshot commands are not yet released).

<!-- Prettier 3.4 -->
This folder has [VHS] tape files to create gifs for the [Widget Showcase]. To
run them, install VHS from main (the theme and screenshot commands are not yet
released).

Conservar espacios no ASCII al final de línea y principio de siguiente línea (#16619 por @tats-u)

Prettier eliminaba espacios no ASCII al final de la línea y principio de la siguiente línea. Sin embargo, este comportamiento no es consistente con la especificación CommonMark.

https://spec.commonmark.org/0.31.2/#soft-line-breaks

Se eliminan los espacios al final de la línea y al principio de la siguiente línea:

https://spec.commonmark.org/0.31.2/#unicode-whitespace-character

Un carácter de espacio en blanco Unicode es un carácter de la categoría general Unicode Zs, o un tabulador (U+0009), avance de línea (U+000A), avance de página (U+000C) o retorno de carro (U+000D).

Un espacio Unicode es una secuencia de uno o más caracteres de espacio en blanco Unicode.

Un espacio es U+0020.

La especificación CommonMark no menciona espacios no ASCII aquí, por lo que eliminarlos cambia el contenido del documento Markdown.

<!-- Input -->
 EM Space (U+2003) EM Space

 全角スペース (U+3000) 全形空白

<!-- Prettier 3.3 -->
EM Space (U+2003) EM Space

全角スペース (U+3000) 全形空白

<!-- Prettier 3.4 -->
 EM Space (U+2003) EM Space

 全角スペース (U+3000) 全形空白

Evitar salto de línea entre caracteres chinos/japoneses y otros (#16691 por @tats-u)

Los documentos Markdown se convierten principalmente a HTML o componentes de frameworks basados en JavaScript. Esto significa que los párrafos en Markdown eventualmente son procesados por el navegador según reglas CSS. Esto ocurre porque muchos convertidores de Markdown preservan los saltos de línea en los párrafos del Markdown de entrada, y el propio HTML no especifica cómo los navegadores deben manejar los saltos de línea en texto HTML.

Según reglas CSS (CSS Text Module Level 3 o posteriores), los navegadores deberían eliminar los saltos de línea entre caracteres chinos/japoneses en lugar de reemplazarlos con espacios. Sin embargo, esta regla ha sido ignorada durante mucho tiempo por navegadores basados en WebKit o derivados de Webkit (Chrome, Safari, etc.).

Por ejemplo, el siguiente párrafo HTML:

<p>
日本語
汉语
漢語
<p>

generado a partir del siguiente Markdown:

日本語
汉语
漢語

debería renderizarse según las reglas CSS y así lo hace Firefox:

日本語汉语漢語

Sin embargo, Chrome y Safari lo renderizan así:

日本語 汉语 漢語

Esta es la razón por la que debemos evitar que Prettier inserte saltos de línea entre caracteres chinos/japoneses. Decidimos evitar que Prettier obligue a los usuarios a usar un plugin para convertidores de Markdown que concatenen líneas que comienzan o terminan con caracteres chinos/japoneses (remark-join-cjk-lines, por ejemplo).

Además, un salto de línea entre chino/japonés y otros caracteres equivale a un espacio según lo establecido antes de el commit que suspendió una regla concreta en CSS Text Module Level 3 comentándola para corregir un problema en los borradores del CSS Working Group. Firefox sigue esta regla. Por lo tanto, todos los navegadores renderizan el siguiente párrafo:

<!-- prettier-ignore -->
```html
<p>日本語 English 汉语 한국어 漢語</p>

<p></p>

de la siguiente manera:

日本語 English 汉语 한국어 漢語

Sin embargo, Prettier ha insertado saltos de línea entre caracteres chinos/japoneses en Markdown durante mucho tiempo, y entre caracteres chinos/japoneses y latinos en algunos casos desde la versión 3.0.0. Por ejemplo, el siguiente párrafo en Markdown:

日本語English汉语
English
漢語

se formatea así si --prose-wrap tiene un valor distinto a preserve en Prettier 3.x:

日本語English汉语English漢語

Sin embargo, el siguiente HTML, generado por un convertidor de Markdown a HTML basado en el Markdown anterior:

<p>
日本語English汉语
English
漢語
</p>

se renderiza así en todos los navegadores:

日本語English汉语 English 漢語

Esta es la razón por la que también debemos evitar que Prettier inserte saltos de línea alrededor de caracteres chinos/japoneses en Markdown. Vamos a alinear el comportamiento de Prettier con esta regla en una futura versión. Después de eso, los saltos de línea entre chino/japonés y otros caracteres se permitirán nuevamente bajo ciertas reglas.

Una de las pocas excepciones son los espacios y saltos de línea entre letras chinas/japonesas y coreanas. Los siguientes párrafos en Markdown son equivalentes incluso en la versión actual de Prettier:

현재 韓國의 大統領은 尹錫悅이다.
현재
韓國의
大統領은
尹錫悅이다.

Obtendrás el primero si formateas el segundo con --prose-wrap=always y un valor de --print-width suficientemente largo o con --prose-wrap=never, y obtendrás el segundo si formateas el primero con --prose-wrap=always con un valor de --print-width extremadamente corto. Por lo tanto, no necesitamos modificar esos espacios y saltos de línea.

Otra excepción son aquellos entre un carácter chino/japonés y un símbolo significativo en Markdown como *, `, [, y ]. Por ejemplo, el siguiente párrafo en Markdown es equivalente incluso en la versión actual de Prettier:

**Yarn** のCLI経由でフォーマットするには `yarn prettier -w ` を実行してください。
**Yarn**
のCLI経由でフォーマットするには
`yarn prettier -w .`
を実行してください。
<!-- Input (--prose-wrap=always --print-width=20) -->
日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어 日本語 汉语 漢語 English 한국어

日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어

<!-- Prettier 3.3 -->
日本語 汉语 漢語
English 한국어 日本
語 汉语 漢語 English
한국어 日本語 汉语
漢語 English 한국어
日本語 汉语 漢語
English 한국어

日本語汉语漢語
English한국어日本語
汉语漢語
English한국어日本語
汉语漢語
English한국어日本語
汉语漢語
English한국어

<!-- Prettier 3.4 -->
日本語 汉语 漢語 English
한국어
日本語 汉语 漢語 English
한국어
日本語 汉语 漢語 English
한국어
日本語 汉语 漢語 English
한국어

日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어日本語汉语漢語English한국어

Indicar a regexp-util que genere regex compatibles con la bandera u (#16816 por @tats-u)

Los caracteres CJK fuera del BMP (Plano Multilingüe Básico) y las Secuencias de Variación Ideográfica (IVS; selectores de variación dedicados para han/kanji), que ocupan 2 caracteres en las cadenas de JavaScript, no habían sido tratados como CJK. Esto se debía a que Prettier no había pasado la bandera "u" al paquete regexp-util.

En el siguiente ejemplo, "𠮷" (U+20BB7) está fuera del BMP, y "葛󠄀" es una combinación del han "葛" (U+845B) en BMP y un IVS U+E0100. El último requiere una fuente con soporte para Adobe Japan-1 (ej. Yu Gothic UI y Source Han Sans) para renderizarse con una forma diferente al carácter sin IVS (葛).

<!-- Input (--prose-wrap=never) -->
a 字 a 字 a 字
𠮷
𠮷
葛󠄀
葛󠄀


<!-- Prettier 3.3 -->
a 字 a 字 a 字 𠮷 𠮷 葛󠄀 葛󠄀 終

<!-- Prettier 3.4 -->
a 字 a 字 a 字𠮷𠮷葛󠄀葛󠄀終

YAML

Corregir comentario en YAML en elementos multilínea sin espacio antes de # (#16489 por @fyc09)

# Input
123: # hello
# comment

# Prettier 3.3
123:# hello
# comment

# Prettier 3.4
123: # hello
# comment

API

Detener mutación de documentos en prettier.doc.printDocToString (#13315 por @fisker)

Por razones de rendimiento, prettier.doc.printDocToString solía mutar .parts del comando fill durante la impresión. Se convirtió en una función pura para garantizar la corrección de la salida.

Hacer pública getPreferredQuote (#16567 por @sosukesuzuki)

Este cambio convierte la función interna getPreferredQuote en parte de la API pública.

En lenguajes como JavaScript, se pueden usar comillas simples y dobles para literales de cadena. Prettier determina la comilla que envuelve un literal basándose en la cantidad de comillas dentro de la cadena y el valor de la opción singleQuote. Para más detalles, consulta la página Rationale.

La función getPreferredQuote determina la comilla apropiada para envolver un literal de cadena y tiene la siguiente interfaz:

type Quote = '"' | "'";
function getPreferredQuote(
text: string,
preferredQuoteOrPreferSingleQuote: Quote | boolean,
): Quote;

Aquí hay ejemplos de cómo usarla:

import * as prettier from "prettier";

const SINGLE_QUOTE = `'`;
const DOUBLE_QUOTE = `"`;

console.log(prettier.util.getPreferredQuote(`Hello World Test`, SINGLE_QUOTE)); // '
console.log(prettier.util.getPreferredQuote(`Hello World Test`, DOUBLE_QUOTE)); // "
console.log(prettier.util.getPreferredQuote(`'Hello' "World" 'Test'`, SINGLE_QUOTE)); // "
console.log(prettier.util.getPreferredQuote(`"Hello" 'World' "Test"`, DOUBLE_QUOTE)); // '
console.log(prettier.util.getPreferredQuote(`"Hello" "World" "Test"`, SINGLE_QUOTE)); // '
console.log(prettier.util.getPreferredQuote(`'Hello' 'World' 'Test'`, DOUBLE_QUOTE)); // "

Hacer pública esta función beneficiará a desarrolladores de plugins. Dado que es relativamente corta, puedes ver detalles en la implementación.

Corregir carga de archivos de configuración compartida en formato ESM en Node.js 23 (#16857 por @sosukesuzuki)

En Prettier 3.3, intentar cargar un archivo de configuración compartida en formato ESM en Node.js 23 producía estas advertencias, impidiendo cargar las opciones:

[warn] Ignored unknown option { __esModule: true }.
[warn] Ignored unknown option { default: { trailingComma: "es5", tabWidth: 4, singleQuote: true } }.

El problema se debía a una nueva característica de módulos en Node.js 23 llamada require(ESM). Prettier 3.4 lo resuelve, permitiendo cargar las opciones correctamente.

Para más detalles, consulta https://github.com/prettier/prettier/issues/16812.

CLI

Ignorar archivos en el directorio Jujutsu (#16684 por @marcusirgens)

El sistema de control de versiones Jujutsu utiliza el directorio .jj, similar a cómo Git usa .git.

Este cambio agrega .jj a la lista de directorios que Prettier ignora silenciosamente.

Varios

Corregir que la función cursorOffset a veces sea catastróficamente lenta (#15709 por @ExplodingCabbage)

Anteriormente, la función cursorOffset de Prettier podía ser extremadamente lenta en ciertas circunstancias (específicamente cuando el cursor del usuario no estaba contenido dentro de un nodo hoja del AST, y el nodo no-hoja que lo contenía era muy grande y estaba siendo reformateado significativamente por Prettier). Como consecuencia, si usabas Prettier a través de una integración de editor que utilizaba cursorOffset internamente, tu editor a veces se colgaba inexplicablemente al intentar formatear un archivo.

Todos los ejemplos de este fenómeno que conocemos deberían estar corregidos ahora, pero se agradecerían informes de errores sobre cualquier otro caso patológico adicional.