
# Architecture

TailwindPHP est un portage 1:1. La base de code reprend la structure propre à TailwindCSS — mêmes noms de fichiers, même organisation — et isole sous `src/_tailwindphp/` les éléments qui *ne peuvent pas* être portés directement (PHP n’a ni Rust ni V8). Cette page présente le pipeline de compilation, l’organisation des sources, la réimplémentation de `lightningcss` et la convention utilisée pour documenter les écarts.

## Le pipeline

Générer CSS passe par plusieurs étapes. Il n’y a pas d’étape de build distincte : chaque appel à `tw::generate()` exécute l’ensemble du pipeline.

```
CSS input          (@import "tailwindcss"; @theme { … })
  │
  ▼
┌──────────────┐
│  Parse CSS   │  css-parser.php → ast.php nodes
└──────┬───────┘
       ▼  design system (theme, utilities, variants)
┌──────────────┐
│ Scan content │  candidate.php — extract class names from HTML
└──────┬───────┘
       ▼  candidates
┌──────────────┐
│   Compile    │  compile.php — candidate → AST, via design-system.php
└──────┬───────┘
       ▼  AST
┌──────────────┐
│   Optimize   │  _tailwindphp/LightningCss.php — nesting, @media, calc()
└──────┬───────┘
       ▼
┌──────────────┐
│  Serialize   │  ast.php toCss()   (minified when requested)
└──────┬───────┘
       ▼
CSS output
```

**Analyse syntaxique.** `css-parser.php` lit l’entrée CSS — `@import`, `@theme`, `@utility`, `@layer` et règles brutes — dans un arbre syntaxique abstrait de nœuds `ast.php` (règles de style, règles @, déclarations). Les directives `@import` pour les modules virtuels (`tailwindcss`, `tailwindcss/preflight`, …) et les chemins de fichiers sont résolus et remplacés à cette étape.

**Construction du système de design.** `theme.php` résout les valeurs du thème (couleurs, espacements, points de rupture) à partir des blocs `@theme` analysés et des valeurs par défaut. `design-system.php` est le registre central qui relie le thème aux recherches d’utilitaires et de variantes définies dans `utilities.php` et `variants.php`.

**Analyse du contenu.** `candidate.php` extrait les classes candidates du contenu fourni (HTML, modèles) et décompose chacune en éléments : utilitaire de base, variantes, modificateurs, valeurs arbitraires et indicateur important.

**Compilation.** `compile.php` transforme chaque candidate en nœuds AST en la recherchant dans le système de design et en appliquant ses variantes et modificateurs. Les candidates qui ne correspondent à aucun utilitaire réel sont écartées.

**Sérialisation et optimisation.** Le `toCss()` de `ast.php` parcourt l’arbre (avec les fonctions d’aide de `walk.php`) et génère la chaîne CSS. Les transformations équivalentes à celles de `lightningcss` dans `_tailwindphp/LightningCss.php` sont appliquées afin que le résultat corresponde à celui produit par TailwindCSS après son étape de post-traitement Rust.

**Minification.** Lorsque `minify` est activé, `toCss()` génère du CSS minifié pendant la sérialisation. `_tailwindphp/CssMinifier.php` assure le passage autonome de la chaîne `tw::minify()`. Voir [Mise en cache et minification](https://tailwindphp.inline0.dev/fr/docs/advanced/caching).

## Organisation des sources

`src/` reprend la structure de TailwindCSS. La seule modification structurelle : le `utilities.ts` de TailwindCSS fait plus de 6,000 lignes ; il est donc réparti dans `src/utilities/`, avec un fichier par catégorie pour faciliter la maintenance.

```
src/
├── _tailwindphp/                # PHP-specific — NOT part of the TailwindCSS port
│   ├── LightningCss.php         # CSS transforms (lightningcss Rust library equivalent)
│   ├── CssMinifier.php          # CSS minification
│   └── lib/                     # Companion library ports (TailwindPHP\Lib\*)
│       ├── clsx/                # clsx port
│       ├── tailwind-merge/      # tailwind-merge port
│       └── cva/                 # CVA port
│
├── plugin/                      # Plugin system
│   └── plugins/
│       ├── typography-plugin.php  # @tailwindcss/typography port
│       └── forms-plugin.php       # @tailwindcss/forms port
│
├── utilities/                   # Split from TailwindCSS utilities.ts (one file per category)
│   ├── accessibility.php        # sr-only, forced-colors
│   ├── backgrounds.php          # bg-*, gradient-*, from-*, via-*, to-*
│   ├── borders.php              # border-*, rounded-*, divide-*, outline-*
│   ├── effects.php              # shadow-*, opacity-*, mix-blend-*
│   ├── filters.php              # blur-*, brightness-*, contrast-*, …
│   ├── flexbox.php              # flex-*, grid-*, gap-*, justify-*, align-*
│   ├── interactivity.php        # cursor-*, scroll-*, touch-*, select-*
│   ├── layout.php               # display, position, z-*, overflow-*, …
│   ├── masks.php                # mask-linear-*, mask-radial-*, mask-conic-*
│   ├── sizing.php               # w-*, h-*, min-*, max-*, size-*
│   ├── spacing.php              # m-*, p-*, space-*
│   ├── svg.php                  # fill-*, stroke-*
│   ├── tables.php               # border-collapse, table-layout
│   ├── transforms.php           # translate-*, rotate-*, scale-*, skew-*
│   ├── transitions.php          # transition-*, duration-*, ease-*, delay-*
│   └── typography.php           # font-*, text-*, leading-*, tracking-*
│
├── utils/                       # Helper functions (ported from utils/)
│
├── index.php                    # Main entry — compile(), cn(), variants(), merge(), join()
├── ast.php                      # AST nodes and toCss()
├── candidate.php                # Candidate parsing (class name → parts)
├── compile.php                  # Candidate to CSS compilation
├── css-functions.php            # theme(), --theme(), --spacing(), --alpha()
├── css-parser.php               # CSS parsing
├── design-system.php            # Central registry for utilities/variants
├── plugin.php                   # Plugin system (PluginInterface, PluginAPI, PluginManager)
├── theme.php                    # Theme value resolution
├── utilities.php                # Utility registration and lookup
├── value-parser.php             # CSS value parsing
├── variants.php                 # Variant handling (hover, focus, responsive, …)
└── walk.php                     # AST traversal
```

## L’équivalent de lightningcss

TailwindCSS délègue le post-traitement CSS — imbrication, gestion des requêtes média, simplification des valeurs — à [lightningcss](https://lightningcss.dev/), un analyseur, transformateur et minificateur écrit en Rust. PHP ne peut pas charger de bibliothèque Rust ; `src/_tailwindphp/LightningCss.php` réimplémente donc les transformations dont TailwindPHP dépend réellement, en produisant une sortie identique octet pour octet dans les cas couverts par la suite de tests.

Les transformations confirmées comprennent :

| Transformation | Effet |
|-----------|--------------|
| Aplatissement de l’imbrication | Résout les sélecteurs `&` avec les règles `:is(…)` de référence et aplatit les règles imbriquées (`handleNesting()` dans `ast.php`, portage de la passe TailwindCSS) ; `transformNesting` rétrograde le niveau des imbrications restantes sous le premier niveau contenant des déclarations |
| Aplatissement des règles conditionnelles | Aplatit sur place les `@media`, `@supports`, `@container` et `@starting-style` imbriqués, en préservant l’ordre source, et ne fusionne que les éléments frères directement adjacents ayant des conditions identiques |
| Ordre des déclarations | Réordonne les déclarations selon la chaîne de gestion des déclarations de lightningcss, afin que les propriétés suivent l’ordre de référence (`reorderDeclarations`) |
| Simplification de `calc()` | Simplifie les expressions `calc()` (`simplifyCalcExpressions`) |
| Suppression des zéros initiaux | `0.5` → `.5` (`normalizeLeadingZeros`) |
| Espacement des fonctions de transformation | Normalise les espaces dans les fonctions de transformation (`normalizeTransformFunctions`) |
| Normalisation des valeurs de grille | Ajoute des espaces autour de `/` dans les valeurs span ; convertit les entiers seuls en px pour `grid-template-*` (`normalizeGridValues`) |
| Normalisation des couleurs | Normalise la syntaxe des couleurs et évalue `color-mix()` en `oklab()` (`normalizeColors`, `evaluateColorMix`) |
| Mise entre guillemets de URL | `url(./x.jpg)` → `url("./x.jpg")` (`normalizeUrlQuoting`) |
| Préfixes vendeurs | Ajout de préfixes équivalents à Autoprefixer (`addVendorPrefixes`) |

Ce fichier est volontairement isolé dans `_tailwindphp/` et marqué `@port-deviation:replacement` : il représente une dépendance externe au lieu de porter le code source de TailwindCSS.

## Marqueurs d’écart du portage

Chaque fichier d’implémentation comporte des marqueurs `@port-deviation:*` dans son bloc de documentation, qui indiquent où et pourquoi l’implémentation PHP s’écarte de la version originale TypeScript. Ainsi, en comparant PHP au code source de TailwindCSS, le lecteur sait toujours si une différence est intentionnelle.

| Marqueur | Signification |
|--------|---------|
| `@port-deviation:none` | Portage direct 1:1 sans écart notable |
| `@port-deviation:async` | PHP utilise du code synchrone au lieu de async/await |
| `@port-deviation:storage` | Structures de données différentes (tableau PHP contre Map/Set JS) |
| `@port-deviation:types` | Annotations PHPDoc au lieu des types TypeScript |
| `@port-deviation:sourcemaps` | Suivi des source maps omis |
| `@port-deviation:enum` | Constantes PHP au lieu des énumérations TypeScript |
| `@port-deviation:errors` | Approche différente de la gestion des erreurs |
| `@port-deviation:replacement` | Implémentation PHP remplaçant une bibliothèque externe (e.g. lightningcss) |
| `@port-deviation:helper` | Fonction auxiliaire propre à PHP, absente de l’original |
| `@port-deviation:performance` | Optimisation propre à PHP qui préserve une sortie identique |
| `@port-deviation:omitted` | Module/fonctionnalité entièrement non porté (hors périmètre) |

Pour consulter les marqueurs `@port-deviation:performance` et savoir comment la parité est assurée, voir [Performances et tests](https://tailwindphp.inline0.dev/fr/docs/advanced/performance).
