Saltar al contenido principal

Prettier 1.10: Un año de Prettier 🎂

· 14 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 →

¡Feliz Prettier-versario! Es increíble que Prettier se haya lanzado hace solo un año y ya haya alcanzado una adopción masiva y un gran número de colaboradores. Para esta edición especial, haremos una pequeña retrospectiva del proyecto.

Además, es un lanzamiento emocionante en sí mismo porque Prettier ahora tiene soporte parcial para archivos .vue y se ha refactorizado su código interno para incluir una API de plugins adecuada que permita soportar diferentes lenguajes.

Retrospectiva​

Desde que gofmt salió en 2013, yo (@vjeux) me obsesioné con la idea del formateo automático. Empecé a ver constantemente problemas que resolvería un formateador automático: discusiones sobre estilos de código, tener que formatear manualmente, dificultad para crear herramientas de codemod…

Cuando el diciembre pasado había no una sino dos personas trabajando independientemente en un "pretty printer" para JavaScript, ¡fue una señal! Pieter Vanderwerff construyó uno en Reason basado en la infraestructura de Flow y James Long en JavaScript. Yo asumí el rol de animador configurando la misma suite de pruebas para ambos proyectos, ejecutando sus formateadores en bases de código existentes y extrayendo listas de cosas que no se formateaban bien.

Lamentablemente, tras las vacaciones, ambos tuvieron que volver a sus trabajos principales :( Decidí intervenir y convencer a mi manager para trabajar en esto a tiempo completo. James había hecho open source de su proyecto (Prettier) y yo tenía más experiencia con JavaScript, así que decidí que este sería el proyecto en el que trabajaría.

Aquí hay una lista de algunas cosas que funcionaron bien durante este proyecto.

Dedica tiempo a las notas de lanzamiento​

Las notas de lanzamiento tienen una propiedad interesante: se comparten con frecuencia, incluso si el contenido es mediocre. Todo el mundo parece querer saber que se ha lanzado la versión 1.5.8 de algún software. Esta es una gran oportunidad para promocionar tu proyecto.

En los lanzamientos de Prettier, dediqué mucho tiempo a explicar la lógica detrás de todos los cambios y hablé de aspectos que probablemente merecerían una publicación de blog independiente (¡como esta!). Además, es probable que te dé pereza y encuentres excusas para no escribir esa entrada, pero realmente quieres publicar la nueva versión, así que funciona como un buen mecanismo de presión.

Proceso de toma de decisiones claro​

Las reglas de estilo son uno de los temas más controvertidos y al mismo tiempo se necesitaban tomar muchas decisiones. Intenté diseñar un proceso de toma de decisiones que nos permitiera avanzar.

La gente encuentra todo tipo de argumentos emocionales para convencerte de que su opinión sobre el estilo es la mejor. Necesitábamos algo puramente racional para que, aunque no fuera lo que la gente preferiría, no pudieran argumentar contra la metodología.

La mejor solución que encontré fue contar cuántas veces se usaba cada variante en la base de código de Facebook. Es fácil para mí ejecutarlo y proporcionar números relativos (el estilo A se usa 5 veces más que el estilo B) para convencer a la gente. Si una base de código tan grande, escrita por miles de personas a lo largo de los años tiene un ganador, puede que no sea el mejor pero es poco probable que sea enormemente controvertido.

No todo podía resolverse así. Algunas cosas no tenían un ganador claro o no era obvio cómo idear un algoritmo para formatearlas bien. En esos casos, era importante tener un proceso de escalamiento con una sola persona tomando la decisión final (yo). Así pudimos avanzar sin necesidad de buscar consenso, lo que probablemente habría sido muy difícil.

Open source como conejillos de Indias​

Un impresor de código completo es uno de esos proyectos que necesita estar casi perfecto para implementarse en una base de código grande como Facebook. La primera impresión es extremadamente importante y es muy difícil lograr algo que sea correcto (que no introduzca JavaScript inválido o código que se comporte diferente) para todos los casos extremos.

Mi plan inicial era trabajar solo, escondido del mundo exterior durante 6 meses hasta que todo estuviera perfecto, y luego hacer que la gente lo adoptara. Lo que no esperaba es que la comunidad open source no tuviera ese mismo nivel de exigencia y comenzara a usarlo mucho antes. Los riesgos de usarlo en un proyecto personal son muy diferentes que en millones de líneas de código en Facebook.

Terminó siendo muy beneficioso para el proyecto recibir retroalimentación durante el proceso hasta que finalmente estuvo listo para usarse en Facebook.

Open source como colaboradores​

Durante los primeros 6 meses del proyecto, trabajé a tiempo completo y terminé escribiendo solo la mitad de los commits. ¡Eso es impresionante de por sí! No solo el rendimiento fue dos veces mejor en el proyecto mismo, sino que la gente trabajó en cosas en las que yo no habría invertido tiempo: integraciones con todos los editores del planeta, un fuzzer para encontrar errores, soporte para TypeScript, infraestructura para analizar múltiples lenguajes en el mismo archivo, y más.

Aunque no usamos todas esas funciones en Facebook, muchas resultaron útiles. El soporte para CSS-in-JS facilitó formatear fragmentos GraphQL en literales de plantilla. La gran cantidad de usuarios también ayudó a detectar errores oscuros que eventualmente enfrentaríamos, y muchas personas contribuyeron a solucionarlos.

Lo mejor es que dejé de trabajar a tiempo completo hace 6 meses y el proyecto continuó bajo el liderazgo de @azz. ¡Quiero agradecer a todos los que ayudaron de diversas maneras, es emocionante hacer historia juntos!

El open source ha hecho maravillas por el proyecto, entregando un enorme valor para Facebook (casi todos nuestros archivos JavaScript ahora están formateados) y para la industria en general, como lo demuestra la gran adopción.

Herramientas: Pruebas de instantáneas con Jest y el Playground​

Todas estas contribuciones fueron posibles porque era fácil reportar errores, contribuir y revisar código. Las dos herramientas más impactantes en este proyecto fueron las pruebas de instantáneas con Jest y el playground.

Las pruebas de instantáneas son maravillosas para un formateador. Agregar nuevas pruebas es muy sencillo: solo crea un archivo en la carpeta de pruebas con el código que quieres formatear y ejecuta Jest, ¡voilà! Cuando cambias algo, puedes ver cómo varios ejemplos se imprimirían diferente, y luego decides si es mejor o no. Para un revisor también es genial: puedes ver el antes/después de todos los cambios. Terminé prestando más atención a las instantáneas que a la implementación misma.

El playground es una excelente manera de reproducir errores o probar Prettier sin instalar el entorno de desarrollo ni estar en la rama correcta. Ha demostrado ser extremadamente valioso para que la gente proporcione reportes de errores accionables y de alta calidad.

Destacados​

Soporte para Componentes de un solo archivo de Vue (#3563) por @vjeux​

Existe mucha demanda para los Componentes de un solo archivo (SFC) de Vue (#2097). Hemos introducido soporte parcial: todo el HTML se imprime tal cual, pero ahora las etiquetas <script> y <style> se formatean con Prettier.

¡Para usarlo, simplemente ejecuta prettier en tus archivos *.vue!

API de plugins para Prettier (#3536) por @azz​

A medida que Prettier para JavaScript se ha estabilizado, recientemente hemos tenido colaboradores interesados en añadir nuevos lenguajes a Prettier, particularmente hemos recibido pull requests para agregar soporte para Python y PHP. Queremos mantener el paquete central prettier portable y mantenible, pero también deseamos brindar la oportunidad de ejecutar Prettier en más lenguajes. Para ello, hemos introducido una API de plugins! Los plugins de Prettier pueden aportar parsers y/o printers al formateador. Se tratan como ciudadanos de primera clase y pueden incluso contribuir al soporte de incrustación (por ejemplo, formatear tu lenguaje dentro de Markdown).

Usar plugins es tan simple como instalarlos mediante npm/yarn y ejecutar Prettier como lo harías normalmente, ¡sin necesidad de configuración adicional!

Hay tres plugins oficiales en desarrollo:

Estos tres plugins aún están en desarrollo activo y no están listos para código de producción, ¡pero mantente atento a su progreso!

Si estás interesado en ayudar a construir estos plugins, revisa la lista de issues en sus repositorios o ejecútalo contra tu propio código y comienza a reportar bugs. De igual forma, si deseas implementar un nuevo lenguaje en Prettier y necesitas ayuda para comenzar, crea un issue en el repositorio de prettier y te ayudaremos.

Los lenguajes incorporados en Prettier se han refactorizado para expresarse mediante la API de plugins, garantizando así que la API central sea genérica.

Consulta [la documentación][plugin api] para más información.

Ten en cuenta que al ser una característica nueva y significativamente grande, la lanzamos con una etiqueta beta en la documentación. Aunque no anticipamos problemas relevantes, esto significa que podríamos introducir cambios incompatibles en la próxima versión.

Otros cambios​

TypeScript​

Soporte para separadores numéricos (#3580) por @azz​

Los separadores numéricos son una propuesta de ECMAScript en etapa 3. TypeScript 2.7 añadió soporte para ellos, y Prettier ahora los preservará.

// Before
SyntaxError: ',' expected. (1:10)
> 1 | var a = 1_000_000_000;
| ^
2 | var b = 0b1101_0101_1001;
3 | var c = 0xAE_FE_2F;

// After
var a = 1_000_000_000;
var b = 0b1101_0101_1001;
var c = 0xAE_FE_2F;

Flow​

Imprimir comentarios de anotación de tipos de Flow como comentarios (#3449) por @duailibe​

Los comentarios de anotación de tipos de Flow permiten verificación de tipos sin transpilar archivos. Antes de esta versión, Prettier con el parser de flow no imprimía estas anotaciones como comentarios, imposibilitando usar esta característica. Ahora Prettier detecta correctamente si la anotación era un comentario e imprime adecuadamente los comentarios tipo /*: ... */. El trabajo para /*:: ... */ está en progreso.

// Input
let foo: string = "a";

// Before
let foo: string = "a";

// After
let foo: string = "a";

Imprimir comentarios después de parámetros en funciones flecha (#3444) por @duailibe​

Al usar el parser de babylon, existen varios problemas con comentarios de flow donde los comentarios se desplazan. Uno de ellos se corrigió en esta versión. Ahora estamos más cerca de soportar completamente esta característica.

// Before
const run = (cmd /*: string */ /*: Promise<void> */) => {};

// After
const run = (cmd /*: string */) /*: Promise<void> */ => {};

Imprimir paréntesis en FunctionTypeAnnotation cuando arrowParens es "always" (#3616) por @duailibe​

En la última versión añadimos la opción arrowParens. Un área inadvertida fueron las anotaciones de tipo de función en flow. Ahora cuando arrowParens es always, colocaremos paréntesis alrededor de parámetros únicos.

// --arrow-parens always

// Before
type SomeType = {
something: number => number
};

// After
type SomeType = {
something: (number) => number
};

JSX​

Expresiones do inline dentro de JSX (#3607) por @vjeux​

Las "expresiones do" son una propuesta de ECMAScript en etapa 1, y son especialmente útiles en JSX. Sin embargo, el nivel adicional de sangría no es necesario, así que ahora las integramos directamente en el contenedor de expresiones.

// Before
{
do {
// ...
}
}

// After
{do {
// ...
}}

Evitar añadir saltos suaves después de atributos flecha con comentarios (#3641) por @duailibe​

Corrección de un problema menor donde aparecía un salto de línea adicional en atributos JSX.

// --print-width 13 (for demonstration)

// Before
<span
attr={
// comment
() =>
true

}
/>;

// After
<span
attr={
// comment
() =>
true
}
/>;

No envolver elementos JSX como atributos entre () (#3640) por @duailibe​

La especificación JSX incluye una característica oculta que permite pasar un elemento como atributo a otro elemento. Prettier añadía paréntesis alrededor, causando un error de sintaxis. Esto se ha corregido. Nota: aunque algunos parsers interpretan esta característica, ninguna transformación JSX la permite actualmente. El primero en soportarlo será Babel 7, actualmente en beta.

// Before
<Foo
content=(
<div>
<div />
</div>
)
/>

// After
<Foo
content=<div>
<div />
</div>
/>

SCSS​

Imprimir comentarios dentro de selectores tal cual (#3649) por @vjeux​

Lamentablemente, el parser CSS que usamos para selectores no soporta comentarios. Existía un caso donde los comentarios en selectores podían moverse a líneas con comentarios. Esto ya está solucionado.

/* Before */

// Foo
.foo,
// Bar .bar {
display: block;
}

/* After */

// Foo
.foo,
// Bar
.bar {
display: block;
}

GraphQL​

Actualizar parser de GraphQL (#3605) por @vjeux​

La especificación GraphQL evoluciona y Prettier ahora soporta tres nuevas características:

Capacidad de anotar tipos con descripciones de texto

"""
Type description
"""
type Foo {
"some description"
someProperty: String!

"""
some really
long description
"""
someOtherProperty: [String!]!
}

Omitir {} cuando no hay contenido

extend enum Site @onEnum

Posibilidad de extender todos los tipos

extend input InputType {
other: Float = 1.23e4
}

Markdown​

Reemplazar saltos de línea con líneas duras en multiparser (#3611) por @ikatyang​

Al incrustar JavaScript dentro de una cita en bloque Markdown, el carácter > de la cita se eliminaba. Esto ya está corregido.

<!-- before -->

> ````md
> <!-- prettier-ignore -->
> ```js
ugly ( code ) ;
```
> ````

<!-- after -->

> ````md
> <!-- prettier-ignore -->
> ```js
> ugly ( code ) ;
> ```
> ````

Ajustar comillas en títulos de enlaces Markdown según la opción singleQuote (#3481) por @j-f1​

Anteriormente todos los títulos de enlaces usaban comillas ". Ahora respetan la opción singleQuote. Usaremos comillas () si el título contiene tanto ' como ".

<!-- --single-quote -->

<!-- Before -->

[ref]: https://prettier.io "Prettier"
[other-ref]: https://example.com "Shakespeare's \"Romeo and Juliet\" is a famous play"

<!-- after -->

[ref]: https://prettier.io 'Prettier'
[other-ref]: https://example.com (Shakespeare's "Romeo and Juliet" is a famous play)

Imprimir referencias de imágenes sin texto alternativo en Markdown (#3643) por @duailibe​

Corregido un caso extremo con referencias de imágenes sin texto alternativo que causaba que Prettier fallara.

<!-- before -->
TypeError: doc is null

<!-- after -->
![][logo]

[logo]: https://github.com/prettier/prettier-logo/blob/master/images/prettier-logo-light.png?raw=true

Respetar tabWidth para la sangría de listas (#3694) por @ikatyang​

Antes forzábamos 2 espacios para la sangría de listas. Ahora consideramos tadWidth.

<!-- --tab-width 4 -->

<!-- before -->
* one
* two

<!-- after -->
* one
* two

API​

Añadir campo options a getSupportInfo() (#3433) por @ikatyang​

prettier.getSupportInfo().options ahora contiene un array de opciones soportadas por Prettier.

Buscar .editorconfig solo hasta el directorio del VCS (#3559) por @josephfrazier​

Diagnosticar problemas donde Prettier formatea diferente entre personas con el mismo repositorio era confuso. Como Prettier soporta archivos .editorconfig y buscábamos hasta ~/.editorconfig, esto podía alterar el formato. Ahora solo buscamos hasta el directorio raíz del proyecto.

CLI​

Centralizar toda la logística CLI en un logger (#3515) por @azz​

La opción --loglevel no se respetaba en algunos casos, ahora se respeta para todo el registro de la CLI.

# Before
$ prettier --loglevel silent --write test.js
test.js 91ms

# After
$ prettier --loglevel silent --write test.js

Salida de archivos tal cual si están ignorados (#3618) por @duailibe​

Hemos corregido el comportamiento de la CLI con archivos ignorados. Anteriormente, cuando un archivo era ignorado por .prettierignore, la CLI no producía ninguna salida. Esto afectaba a las integraciones de editores. El comportamiento actual es:

  • Con --write: no leer ni escribir en el archivo ignorado.

  • Sin --write: leer el archivo ignorado y producir su contenido tal cual.

Integraciones con Editores​

Añadir extensiones PostCSS a getSupportInfo() (#3454) por @ardevelop​

Algunas integraciones de editores usan la función getSupportInfo de Prettier para soportar dinámicamente todos sus lenguajes. Esto añade soporte para archivos *.pcss.

Añadir "JSON con comentarios" a getSupportInfo() (#3496) por @thorn0​

De manera similar, también se detectará "JSON con comentarios".


🎂