
# Formateador

Phasis incluye un formateador nativo de JavaScript basado en su propio analizador. Vuelve a imprimir el código fuente con reglas de disposición compatibles con prettier, completamente en PHP: sin Node.js, sin paquetes de formateo interpretados y sin procesos externos.

## formatSource

```php
public static function formatSource(
    string $source,
    string $sourceType = 'script',
    ?FormatOptions $options = null,
): string
```

El punto de entrada de una sola llamada en `Phasis\Formatter\Formatter`. `$sourceType` selecciona el lenguaje: `script` o `module` para JavaScript, `json` o `css`. JavaScript analiza según el objetivo indicado, vuelve a asociar los comentarios y genera la salida con el ancho configurado.

```php
use Phasis\Formatter\Formatter;
use Phasis\Formatter\FormatOptions;

$formatted = Formatter::formatSource(
    "const a={x:1,y:2};",
    'script',
    new FormatOptions(useTabs: true, singleQuote: true),
);
// "const a = { x: 1, y: 2 };\n"
```

El código fuente no válido genera el mismo `Phasis\Exceptions\SyntaxError` que el analizador, con línea, columna y desplazamiento.

## FormatOptions

Las opciones de disposición reflejan las de prettier 3.x y usan sus valores predeterminados:

| Opción          | Valor predeterminado    | Significado                                                        |
| --------------- | ---------- | -------------------------------------------------------------- |
| `printWidth`    | `80`       | Ancho de línea objetivo al que se ajusta la disposición.                |
| `tabWidth`      | `2`        | Espacios por nivel de sangría (y ancho medido de una tabulación).     |
| `useTabs`       | `false`    | Sangría con tabulaciones en lugar de espacios.                            |
| `semi`          | `true`     | Punto y coma en las instrucciones.                                          |
| `singleQuote`   | `false`    | Preferir `'` frente a `"` cuando requiere menos escapes.              |
| `trailingComma` | `'all'`    | `'all'`, `'es5'` o `'none'`.                                 |
| `bracketSpacing`| `true`     | Espacios dentro de las llaves de objetos: `{ a }` frente a `{a}`.             |
| `arrowParens`   | `'always'` | `'always'` o `'avoid'` para funciones flecha de un solo parámetro.  |

## CSS

`formatSource($css, 'css')` formatea hojas de estilo con la disposición de hojas de estilo de prettier: un selector por línea en listas de selectores, una declaración por línea, espaciado normalizado de combinadores y valores, listas sencillas de valores agrupadas hasta llenar la línea, listas separadas por comas con un elemento por línea para sombras y degradados, argumentos de función que se mantienen juntos o se separan por completo, líneas en blanco y comentarios conservados, y preludios intactos para reglas at desconocidas como Tailwind de `@apply`. Los selectores compuestos largos se dividen en los combinadores descendientes, y los argumentos demasiado largos de las pseudoclases se ajustan dentro de sus paréntesis.

## JSON

`formatSource($json, 'json')` reutiliza el analizador y los generadores de JavaScript con las reglas JSON de prettier: las claves mantienen las comillas, las cadenas siguen entre comillas dobles independientemente de `singleQuote`, nunca aparecen comas finales y se conservan los comentarios `//` dentro del documento.

## Reglas de disposición

El generador implementa el modelo de documentos de prettier: los grupos se aplanan si caben en el ancho de impresión y se dividen en caso contrario; los argumentos de llamada se mantienen junto a un argumento final de función u objeto; las cadenas de miembros se dividen antes de cada punto cuando exceden el ancho de línea; los objetos escritos en varias líneas se mantienen así, y se conserva como máximo una línea en blanco entre instrucciones. Con entrada formateada por prettier y opciones coincidentes, el formateador produce resultados idénticos byte por byte en código real; su conjunto de conformidad lo verifica exactamente con archivos de prueba generados por prettier.

## Comentarios

Los comentarios se recopilan durante la tokenización (`Parser::setCollectComments(true)`, expuestos en el analizador para las herramientas) y se vuelven a asociar al árbol como elementos iniciales, finales o sueltos. Los comentarios de línea conservan sus propias líneas, los comentarios finales en la misma línea permanecen en su instrucción, se conservan las líneas en blanco alrededor de los comentarios y los bloques `/** ... */` se reindentan alineando su margen `*`.

## Garantías

El conjunto de pruebas hace cumplir tres invariantes en cada salida formateada:

- La salida se vuelve a analizar como un programa equivalente (salvo las ubicaciones).
- Todos los comentarios de la entrada se conservan en la salida.
- El formato es idempotente: volver a formatear la salida no cambia nada.

## Rendimiento

El formateo funciona a la velocidad del analizador: los archivos reales se formatean en decenas de milisegundos, y un JavaScript típico de un proyecto se formatea de principio a fin en mucho menos de un segundo en un solo proceso.
