
# Architektur

TailwindPHP ist eine 1:1-Portierung. Die Codebasis spiegelt die Struktur von TailwindCSS wider – dieselben Dateinamen und dieselbe Organisation – und isoliert die Teile, die sich *nicht* direkt portieren lassen (PHP hat weder Rust noch V8), unter `src/_tailwindphp/`. Diese Seite führt durch die Kompilierungspipeline, die Quellstruktur, die `lightningcss`-Neuimplementierung und die Konvention zur Dokumentation von Abweichungen.

## Die Pipeline

Das Erzeugen von CSS läuft in mehreren Schritten ab. Es gibt keinen separaten Build-Schritt – jeder Aufruf von `tw::generate()` führt die vollständige Pipeline aus.

```
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
```

**Parsen.** `css-parser.php` liest die CSS-Eingabe – `@import`, `@theme`, `@utility`, `@layer`, rohe Regeln – in einen abstrakten Syntaxbaum aus `ast.php`-Knoten ein (Stilregeln, At-Regeln, Deklarationen). `@import`-Direktiven für virtuelle Module (`tailwindcss`, `tailwindcss/preflight`, …) und Dateipfade werden in diesem Schritt aufgelöst und ersetzt.

**Designsystem erstellen.** `theme.php` löst Theme-Werte (Farben, Abstände, Breakpoints) aus den geparsten `@theme`-Blöcken und den Standardwerten auf. `design-system.php` ist die zentrale Registry, die das Theme mit den in `utilities.php` und `variants.php` definierten Utility- und Varianten-Lookups verknüpft.

**Inhalte durchsuchen.** `candidate.php` extrahiert aus den angegebenen Inhalten (HTML, Vorlagen) mögliche Klassennamen und zerlegt sie in Bestandteile: Basis-Utility, Varianten, Modifikatoren, beliebige Werte und Wichtigkeitsmarkierung.

**Kompilieren.** `compile.php` wandelt jeden Kandidaten in AST-Knoten um, indem es ihn im Designsystem nachschlägt und seine Varianten und Modifikatoren anwendet. Kandidaten, die keiner echten Utility entsprechen, werden verworfen.

**Serialisieren und optimieren.** Der `toCss()`-Prozess von `ast.php` durchläuft den Baum (mit Hilfsfunktionen aus `walk.php`) und gibt den CSS-String aus. Die Transformationen in `_tailwindphp/LightningCss.php`, die `lightningcss` entsprechen, werden angewendet, damit die Ausgabe dem Ergebnis von TailwindCSS nach der Rust-Nachverarbeitung entspricht.

**Minifizieren.** Wenn `minify` aktiviert ist, gibt `toCss()` während der Serialisierung minifiziertes CSS aus. `_tailwindphp/CssMinifier.php` übernimmt den eigenständigen `tw::minify()`-Durchlauf. Siehe [Caching und Minifizierung](https://tailwindphp.inline0.dev/de/docs/advanced/caching).

## Quellstruktur

`src/` spiegelt TailwindCSS wider. Die einzige strukturelle Änderung: TailwindCSSs `utilities.ts` umfasst mehr als 6,000 Zeilen und ist daher zur besseren Wartbarkeit in `src/utilities/` aufgeteilt, mit einer Datei pro Kategorie.

```
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
```

## Das Gegenstück zu lightningcss

TailwindCSS überlässt seine CSS-Nachverarbeitung – Verschachtelung, Media-Query-Verarbeitung und Vereinfachung von Werten – [lightningcss](https://lightningcss.dev/), einem in Rust geschriebenen Parser, Transformer und Minifier. PHP kann keine Rust-Bibliothek laden, daher implementiert `src/_tailwindphp/LightningCss.php` die Transformationen neu, auf die TailwindPHP tatsächlich angewiesen ist. Für die vom Testsatz abgedeckten Fälle entsteht dabei eine byteidentische Ausgabe.

Bestätigte Transformationen umfassen:

| Transformation | Wirkung |
|-----------|--------------|
| Verschachtelung auflösen | Löst `&`-Selektoren mit den `:is(…)`-Regeln der Referenz auf und flacht verschachtelte Regeln ab (`handleNesting()` in `ast.php`, eine Portierung des TailwindCSS-Durchlaufs); `transformNesting` stuft die Verschachtelung unterhalb der ersten Ebene mit Deklarationen herab |
| Bedingte At-Regeln abflachen | Flacht verschachtelte `@media`, `@supports`, `@container` und `@starting-style` an Ort und Stelle ab, erhält die Quellreihenfolge und führt nur direkt benachbarte Geschwister mit identischen Bedingungen zusammen |
| Reihenfolge der Deklarationen | Ordnet Deklarationen gemäß der Handler-Kette von lightningcss neu, sodass Eigenschaften in der Referenzreihenfolge ausgegeben werden (`reorderDeclarations`) |
| `calc()`-Vereinfachung | Vereinfacht `calc()`-Ausdrücke (`simplifyCalcExpressions`) |
| Führende Null entfernen | `0.5` → `.5` (`normalizeLeadingZeros`) |
| Abstände in Transform-Funktionen | Vereinheitlicht Abstände innerhalb von Transform-Funktionen (`normalizeTransformFunctions`) |
| Grid-Werte normalisieren | Fügt in Span-Werten Leerzeichen um `/` ein, wandelt reine Ganzzahlen für `grid-template-*` in px um (`normalizeGridValues`) |
| Farben normalisieren | Vereinheitlicht die Farbsyntax und wertet `color-mix()` zu `oklab()` aus (`normalizeColors`, `evaluateColorMix`) |
| URL-Anführungszeichen | `url(./x.jpg)` → `url("./x.jpg")` (`normalizeUrlQuoting`) |
| Herstellerpräfixe | Präfixe wie bei Autoprefixer (`addVendorPrefixes`) |

Diese Datei ist absichtlich unter `_tailwindphp/` isoliert und als `@port-deviation:replacement` markiert – sie steht stellvertretend für eine externe Abhängigkeit, statt TailwindCSS-Quellcode zu portieren.

## Markierungen für Abweichungen bei der Portierung

Jede Implementierungsdatei enthält in ihrem Docblock `@port-deviation:*`-Markierungen, die angeben, wo und warum die PHP-Implementierung vom TypeScript-Original abweicht. So muss sich niemand beim Vergleich von PHP mit dem TailwindCSS-Quellcode fragen, ob ein Unterschied beabsichtigt ist.

| Markierung | Bedeutung |
|--------|---------|
| `@port-deviation:none` | Direkte 1:1-Portierung ohne wesentliche Abweichungen |
| `@port-deviation:async` | PHP verwendet synchronen Code statt async/await |
| `@port-deviation:storage` | Andere Datenstrukturen (PHP-Array statt JS Map/Set) |
| `@port-deviation:types` | PHPDoc-Annotationen statt TypeScript-Typen |
| `@port-deviation:sourcemaps` | Source-Map-Verfolgung ausgelassen |
| `@port-deviation:enum` | PHP-Konstanten statt TypeScript-Enums |
| `@port-deviation:errors` | Anderer Ansatz zur Fehlerbehandlung |
| `@port-deviation:replacement` | PHP-Implementierung ersetzt eine externe Bibliothek (e.g. lightningcss) |
| `@port-deviation:helper` | Hilfsfunktion speziell für PHP, die im Original fehlt |
| `@port-deviation:performance` | Für PHP spezifische Optimierung, die identische Ausgabe beibehält |
| `@port-deviation:omitted` | Gesamtes Modul/Feature nicht portiert (außerhalb des Umfangs) |

Zu den `@port-deviation:performance`-Markierungen und dazu, wie die Parität sichergestellt wird, siehe [Leistung und Tests](https://tailwindphp.inline0.dev/de/docs/advanced/performance).
